I'm using Django Rest Framework to build an API where I have the following models of Users making, confirming and showing interest on Events:
models.py
class User(AbstractBaseUser, PermissionsMixin):
user_name = models.CharField(_("user name"), max_length=150, unique=True)
slug = AutoSlugField(populate_from='user_name', unique=True)
class Event(models.Model):
name = models.CharField(max_length=100, blank=False, null=False)
owner = models.ForeignKey(User, related_name="owned_events", on_delete=models.SET_NULL, blank=True, null=True)
confirmed = models.ManyToManyField(User, related_name="confirmed_events", blank=True)
interested = models.ManyToManyField(User, related_name="interested_events", blank=True)
to serialize it I used the following code as I found here and at the DRF docs:
serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = [
"url",
"user_name",
"password",
]
extra_kwargs = { "password": {"write_only": True} }
class EventSerializer(serializers.HyperlinkedModelSerializer):
owner = UserSerializer(required=False)
confirmed = UserSerializer(required=False, many=True)
interested = UserSerializer(required=False, many=True)
class Meta:
model = Event
lookup_field = 'slug'
extra_kwargs = { 'url': {'lookup_field': 'slug'} }
fields = [
"url",
"owner",
"name",
"confirmed",
"interested",
]
It works just fine like that, but I wanted the UserSerializer to show confirmed and interested events of each user just like each event shows the users confirmed and interested. I changed serializers and got the url of each event, like that:
serializers.py with HyperlinkedRelatedField on UserSerializer
class UserSerializer(serializers.HyperlinkedModelSerializer):
confirmed_events = serializers.HyperlinkedRelatedField(
queryset=Event.objects.all(),
view_name='event-detail',
lookup_field='slug',
many=True,
required=False
)
interested_events = serializers.HyperlinkedRelatedField(
queryset=Event.objects.all(),
view_name='event-detail',
lookup_field='slug',
many=True,
required=False
)
class Meta:
model = User
fields = [
"url",
"user_name",
"password",
"confirmed_events",
"interested_events",
]
extra_kwargs = { "password": {"write_only": True} }
This got me the following JSON from the User model:
{
"user_name": "d",
"confirmed_events": [],
"interested_events": [
"http://localhost:8000/events/eqwer-2/",
"http://localhost:8000/events/test/",
"http://localhost:8000/events/test-2/",
"http://localhost:8000/events/test-3/",
]
}
And from the Event model:
{
"url": "http://localhost:8000/events/eqwer-2/",
"owner": null,
"name": "eqwer",
"slug": "eqwer-2",
"confirmed": [],
"interested": [
{
"user_name": "d",
"confirmed_events": [],
"interested_events": [
"http://localhost:8000/events/eqwer-2/",
"http://localhost:8000/events/test/",
"http://localhost:8000/events/test-2/",
"http://localhost:8000/events/test-3/",
]
}
]
},
The Event model JSON is fine because it shows each user's data, but I wanted the User JSON to show each event data instead of just the event URL, it'd be something like:
{
"user_name": "d",
"confirmed_events": [],
"interested_events": [
{
"url": "http://localhost:8000/events/eqwer-2/",
"owner": null,
"name": "eqwer",
"slug": "eqwer-2",
},
]
}
Create a separate serializer for interested_events
like so:
class InterestedEventsSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
fields = ('url', 'owner', 'name', 'slug')
And in your UserSerializer
declare the interested_events
using the serializer above:
class UserSerializer(serializers.HyperlinkedModelSerializer):
confirmed_events = ... #
interested_events = InterestedEventsSerializer(many=True)
class Meta:
model = User
fields = [
"url",
"user_name",
"password",
"confirmed_events",
"interested_events",
]
extra_kwargs = { "password": {"write_only": True} }