1

I have two models one Country and one Office model. The office model has a ForeignKey to the Country model:

class Country(TranslatableModel):
    iso = models.CharField(
        max_length=2, verbose_name=_('iso code'),
        help_text="ISO 3166 ALPHA-2 code")
    translations = TranslatedFields(
        name=models.CharField(max_length=100, verbose_name=_('name')),
    )



class Office(models.Model):
    country = models.ForeignKey(
        Country, related_name='country', verbose_name=_('country'))

Now I want to write a django-rest-framework-serializer to send simply {"country": "us"} to get a ForeingKey to the Country Model.

How can I achieve this?

1 Answer 1

1

Read-only

To simply send that representation to the client (read-only, not dealing with creating objects from their deserialized representation)

class OfficeSerializer(serializers.ModelSerializer):
    country = serializers.Field(source='country.iso') # this field of the serializer
                                                      # is read-only

As you can see, it'll read will read country.iso from your office instance, which resolves to 'us' e.g., then gets put into a serializer key called 'country', given you an output of {'country': 'us'}

Writable nested field

Now to complete this, let's write a custom OfficeSerializer.create():

def create(self, validated_data):
    # This expects an input format of {"country": "iso"}

    # Instead of using the ID/PK of country, we look it up using iso field
    country_iso = validated_data.pop('country')
    country = Country.objects.get(iso=country_iso)

    # Create the new Office object, and attach the country object to it
    office = Office.objects.create(country=country, **validated_data)

    # Notice I've left **validated_data in the Office object builder,
    # just in case you want to send in more fields to the Office model

    # Finally a serializer.create() is expected to return the object instance
    return office

As for a OfficeSerializer.update() it's similar:

def update(self, instance, validated_data):
    # instance is your Office object
    # You should update the Office fields here
    # instance.field_x = validated_data['field_x']

    # Let's grab the Country object again

    country_iso = validated_data.pop('country')
    country = Country.objects.get(iso=country_iso)

    # Update the Office object
    instance.country = country
    instance.save()

    return instance
Sign up to request clarification or add additional context in comments.

1 Comment

Yes I know how I can show the countrycodes but how can I update them via POST/PUT API? (The users should only have to set the country code and no IDs, …)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.