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. Software Testing

     
  2. Best WordPress Themes For Photographers And Photography

     
  3. Problems That Affect Conversion Rates

     
  4. Best WordPress Themes in 2017

     
  5. SEO in 2017: Mobile optimization as a competitive advantage

     

News Letter

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