How do I go about re-using the referenced object when using nested Serializers in the drf:
Let's say I have the following two Model
s:
class Address(models.Model):
address_line = models.CharField(max_length=45)
class Person(models.Model):
name = models.CharField(max_length=45)
address = models.ForeignKey(Address)
with Serializer
s:
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Address
class PersonSerializer(serializers.ModelSerializer):
address = AddressSerializer()
class Meta:
model = Person
Right now the Serializers handle creating both the Address
and the Person
together. e.g, when I post the following:
{
'name': 'Alex',
'address': {
'address_line': "1 Here"
}
}
a Person
is created and an Address
is created with the Person
pointing to the newly created Address
.
What is the best way to NOT create a new Address
but to reuse an existing Address
if there is already an Address
with a given address_line
? i.e if I wanted to make the address_line
field unique
? (this object re-use is sometimes called "interning")
What about if there were two address fields address_line1
and address_line2
and I wanted to reuse the Address
object if there already exists an Address
with both of those fields (i.e. unique_together=(address_line1, address_line2)
)?
In function based views we can pass extra context to serializer with "context" parameter with a dictionary. To access the extra context data inside the serializer we can simply access it with "self. context". From example, to get "exclude_email_list" we just used code 'exclude_email_list = self.
The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys. By default the serializer will include a url field instead of a primary key field.
Serializers in Django REST Framework are responsible for converting objects into data types understandable by javascript and front-end frameworks. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.
is_valid perform validation of input data and confirm that this data contain all required fields and all fields have correct types. If validation process succeded is_valid set validated_data dictionary which is used for creation or updating data in DB.
Recently I faced a similar problem, solved it using the following approach (the code has not been tested, its just for reference):
class PersonSerializer(serializers.ModelSerializer):
address = AddressSerializer()
class Meta:
model = Person
def create(self, validated_data):
# pop the validated user data
# assuming its a required field,
# it will always be there in validated_data
address = validated_data.pop('address')
try:
address = Address.objects.get(address_line=address.get('address_line'))
except ObjectDoesNotExist:
address_serializer = AddressSerializer(data=address)
address_serializer.is_valid(raise_exception=True)
address = address_serializer.save()
else:
# save the user and update the validated_data for setting up profile
validated_data['address'] = address
return super(PersonSerializer, self).create(validated_data)
Hope this helps :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With