Django Rest Framework - User profile in nested user

I am using django rest framework to display user info. Each user has some contacts that are saved in the UserProfile (the user profile uses a one-to-one relationship to use). The contacts can be accessed directly in the custom model ( user.contacts

).
I want to show the name (and url) for all of the user's contacts. I wrote the following serializer:

class ContactsUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = get_user_model()
        fields = ("username", "email")


class ContactsSerializer(serializers.ModelSerializer):
    # user = ContactsUserSerializer(many=True) # raises TypeError: 'User' object is not iterable
    class Meta:
        model = UserProfile
        fields = ("user",)


class UserSerializer(serializers.HyperlinkedModelSerializer):
    contacts = ContactsSerializer(many=True)

    class Meta:
        model = get_user_model()
        fields = ("url", "username", "email", "contacts")

      

which return

{
  "url": "http:\/\/localhost:8080\/users\/1\/",
  "username": "test1",
  "email": "",
  "contacts": [
    {
      "user": 2
    },
    {
      "user": 1
    }
  ]
}

      

but I want it to be:

{
  "url": "http:\/\/localhost:8080\/users\/1\/",
  "username": "test1",
  "email": "",
  "contacts": [
    {
      "url": "http://link_to_user",
      "username": "foo"
    },
    {
      "url": "http://link_to_user",
      "username": "bar"
    }
  ]
}

      

How can I achieve this? I already tried to add another serializer for contact users, but it throws an error like: the "User" object is not iterable, and the JSON structure looks a bit awkward: {contacts: [user: {"username": ...},]} which can confuse the API user if they are unsure of the Django user profile.

+3


source to share


1 answer


Yours ContactsSerializer

must be HyperlikedModelSerializer

for the field to url

be automatically added. Since you need the field url

to point to a different model, you actually need to use HyperlinkedRelatedField

and add it as a custom field in the serializer.

class ContactsSerializer(serializers.ModelSerializer):
    url = serializers.HyperlinkedRelatedField(view_name="user-detail", source="user")
    username = serializers.CharField(source="user.username")

    class Meta:
        model = UserProfile
        fields = ("url", "username", )

      



You can use a parameter source

on a field to use a different model field than the displayed one. In this case, we use the fields from the relationship user

in the profile.

user-detail

will be the default view name if you are using a router or following the tutorial. You may need to tweak this to match your detail view.

+6


source







All Articles