Sometimes, I want data in my serialized data that's specific to the user who's logged in. What if there's a data feed and I want to know if a user favorited a specific story upon retrieving that story's info in their client? What if a user logs in and only wants to see unread stories in their feed as opposed to the entire feed?
Problem
I have a user-agnostic set of data: data that has nothing to do with the user viewing the site. I want to make that data somewhat personal by adding attributes (fields) to the data that suit an authenticated (logged-in) user.
Django REST framework easily allows me to serialize the data model. The serialized data has fields corresponding with data model fields.
How can I load data specific to a user who's logged in inside of the serialized, loaded data?
Solution
models.py
class Story(models.Model):
title = models.CharField(max_length="255")
body = models.TextField()
class Favorite(models.Model):
story = models.ForeignKey(Story, related_name="favorites")
user = models.ForeignKey(settings.AUTH_USER_MODEL)
serializers.py
class StorySerializer(serializers.Serializer):
title = serialzers.CharField()
body = serializers.TextField()
is_favorite = serializers.SerializerMethodField('has_favorited_story')
class Meta:
model = Story
fields = ('id',
'title',
'is_favorite',)
def has_favorited_story(self, obj):
"""Check for whether the visiting user fav'd the story.
"""
user = self.context['request'].user
s = obj # the story object
user_has_favorited = False # False by default
try:
user_has_favorited = bool(Favorite.objects.filter(user=user.id,
story=story.id))
except Exception, e:
raise user_has_favorited
return user_has_favorited
Explanation
In order to get the logged-in user data, we're taking advantage of our Serializer class coming with a context
dictionary containing request
, leading us to our user
object, which contains attributes of an authenticated user if someone is logged in. In this case, we're checking to see if there's a Favorite
object stored in our database linked to both the story object and the authenticated user.
Here, we're using the SerializerMethodField
which points to our serializer method called has_favorited_story
. Our method takes one parameter (aside from self
, of course): the obj
, which represents a story object in this case. Since obj
contains Story
attributes, we can grab data specific to one story (the story passed to our serializer method).
If there's a cleaner, better way to do this, just let me know. I wrote it this way just to get the job done and it works.
I miss you so much, Renee.