get_or_create in Django REST Framework

Implementing get_or_create in django API using Rest Framework, with and without unique_together constrain.

Advert

get_or_create is a frequently used and handy function in Django. In Django RWT you can use it as you would use in a regular application if using functional view or class view for processing the data.

With Django Serializes offering many functionality in the box, I wanted to get this done in serialize level. It's staright forward if you don't have any unique_together constrain set to the key fields.

For demo I am using a Guest Model with name, phone number and email, where email and phone is set to be unique_togethe.


class Guest(models.Model):
  first_name = models.CharField(max_length=300)
  last_name = models.CharField(max_length=300, blank=True)
  phone = models.CharField(max_length=300)
  email = models.EmailField(max_length=300)
  
  class Meta:
    unique_together = ('email', 'phone')

Define a new create function and use get_or_create. You are good to go.


class GuestSerializer(serializers.ModelSerializer):
  last_name = serializers.CharField(required=False)
  id = serializers.ReadOnlyField()
  class Meta:
    model = Guest
    fields = ('id','first_name', 'last_name', 'email', 'phone')

  def create(self, validated_data):
    guest, created = Guest.objects.get_or_create(
      email=validated_data['email'], 
      phone=validated_data['phone'], 
      defaults={
        'first_name': validated_data['first_name'], 
        'last_name': validated_data['last_name']
      })
  return guest

unique_together and get_or_create in Django REST

If you have set up unique_together constrains for fields in models then the above code will raise a unique together error before the create functions is invoked.

It's triggered by validation functions in ModelSerializer which inspects unique together before passing control to create function, to get over this a custom validation function to skip the unique together validation will work, because get_or_create is used.


class GuestSerializer(serializers.ModelSerializer):
  last_name = serializers.CharField(required=False)
  id = serializers.ReadOnlyField()
  class Meta:
    model = Guest
    fields = ('id','first_name', 'last_name', 'email', 'phone')

  def run_validators(self, value):
    for validator in self.validators:
      if isinstance(validator, validators.UniqueTogetherValidator):
        self.validators.remove(validator)
    super(GuestSerializer, self).run_validators(value)

  def create(self, validated_data):
    guest, created = Guest.objects.get_or_create(property=validated_data['property'], 
      email=validated_data['email'], 
      phone=validated_data['phone'], 
      defaults={
        'first_name': validated_data['first_name'], 
        'last_name': validated_data['last_name']
      })
  return guest

Comments

Wow ! you have someting to tell us. That's great! Please keep in mind that comments are moderated, we employ rel="nofollow" for links, avoid using a spammy word or a domain in name field, it might end up as a Spam. Thanks for reading.

Last 5 Articles

All Articles >

  1. User Account Details in Django Extended UserModel Serializer

     
  2. Configure and Deploy Django Project on VPS

     
  3. World Wide Web at end of 2016

     
  4. 6 Essential Practices for Ecommerce Blog

     
  5. Text Area Widget in Django Admin

     

News Letter

Subscribe to our email newsletter for useful tips and valuable resources, sent out every new article release.