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.
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.
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