Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework - User Profile in nested User

I'm using django's rest framework to show information about the user. Every user has some contacts that are saved in UserProfile (user profile uses a one-to-one relationship to use). The contacts can be accessed directly in the user model (user.contacts).
I want to display the name (and URL) for all contacts of a user. 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 that? I already tried to add another serializer for the contact users but that raises a Type Error: 'User' object is not iterable and the JSON structure would look a little bit awkward: {contacts: [ user: {"username": ...},]}, which might confuse the user of the API if he isn't confident with Django's User Profile.

like image 902
Matt3o12 Avatar asked Jun 29 '26 16:06

Matt3o12


1 Answers

Your ContactsSerializer would need to be a HyperlikedModelSerializer in order for the url field to be automatically added. Since you need the url field to point to a different model, you would actually need to use a HyperlinkedRelatedField and add it as a custom field on 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 the source parameter to a field to use a different field on the model than what is being displayed. In this case, we are using fields from the user relationship on the profile.

user-detail would be the default view name if you were using a router or followed the tutorial. You may need to adjust this to match your detail view name.

like image 173
Kevin Brown-Silva Avatar answered Jul 01 '26 16:07

Kevin Brown-Silva



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!