0

I am learning Django Rest Framework and creating some APIs with success. Now I am trying to serialize a relation, but I don't know how this works. Here is my code:

class Countries(models.Model):
    country = models.CharField(max_length=255)

    class Meta:
        managed = False
        db_table = 'countries'

class Users(models.Model):
    name = models.CharField(max_length=255)
    email = models.CharField(max_length=255)
    country = models.ForeignKey(Countries, models.DO_NOTHING)
    date = models.DateTimeField()

    class Meta:
        managed = False
        db_table = 'users' 

In views.py

def get(self,request):
        print(UsersSerializer)
        users = Users.objects.all()
        serializer = UsersSerializer(users,many = True)
        return Response(serializer.data)

Serializer:

class UsersSerializer(serializers.ModelSerializer):
    class Meta:
        model = Users
        fields = '__all__'

When I run the API I am getting

[
  {
    "id": 3,
    "name": "dsadasd",
    "email": "[email protected]",
    "date": "2020-05-12T12:15:24Z",
    "country": 1
  }
]

In the country field I am getting country id and I was expecting the country name here...

1
  • 1
    Try use source attribute on UsersSerializer like described django-rest-framework.org/api-guide/fields/#source so defining attribute like country = serializers.CharField(source='country.name') should work Commented May 12, 2020 at 7:40

2 Answers 2

2

You can use the source field argument to retrieve the country instead of the id:

... or may use dotted notation to traverse attributes, such as EmailField(source='user.email'). When serializing fields with dotted notation, it may be necessary to provide a default value if any object is not present or is empty during attribute traversal.

Therefore your serializer should look like this:

class UsersSerializer(serializers.ModelSerializer):
    country = serializers.CharField(source='country.country', default='')

    class Meta:
        model = Users
        fields = ('id', 'name', 'email', 'date', 'country')
        # You may use fields='__all__' but I find the explicit declaration 
        # more flexible.
Sign up to request clarification or add additional context in comments.

Comments

1

you need to change your UsersSerializer to return country name insread of id.

class UsersSerializer(serializers.ModelSerializer):
    country = serializers.SerializerMethodField()  # add this line

    class Meta:
        model = Users
        fields = '__all__'

    def get_country(self, instance):
        return instance.country.country  # return country name

Further read SerializerMethodField.

2 Comments

This is a valid solution as well. Just keep in mind that the source passes through the chosen field's validation methods but you have to provide your validation (if it is needed) to the SrializerMethodField's method. +1 from me :) !
@JohnMoutafis I didn't know about source field validation process, thanks for providing valuable info.

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.