4

I'm building a social app which has a "like" feature, I'm using django-redis to store "like" numbers from every post like this:

from django_redis import get_redis_connection
con = get_redis_connection("default")
con.incr("post" + ":" + id)

From the doc Raw client access

It works great, and I also use django-rest-framework to provide api, ListCreateAPIView to list all posts.Usually it will display any fields you want in the database. The problem here is now I wanna display "like" count from django-redis in this API which means the json return are from my database and django-redis.

I had look around the source code about django-rest-framework

class ListCreateAPIView(mixins.ListModelMixin,mixins.CreateModelMixin,
                    GenericAPIView):
    """
    Concrete view for listing a queryset or creating a model instance.
    """
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

and the list method:

class ListModelMixin(object):
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

It seems like I can only get data from the database queryset(which I use Mysql). Any possible way to return data from django-redis with django-rest-framework?

Solved: Thanks answer from @Rahul Gupta, I do a little hack to work better:

def get_likes(self, obj):
    post_id = obj.id
    post_like = get_redis_connection("default")
    likes = post_like.get("post"+":"+str(post_id))
    if likes == None:
        return 0
    else:
        likes = likes.decode('utf-8')
        return likes
Windsooon
  • 6,864
  • 4
  • 31
  • 50

2 Answers2

2

You can add a 'likes' SerializerMethodField in your PostSerializer to add likes in the serialized representation of the object.

class SocialPostSerializer(serializers.ModelSerializer):

    likes = serializers.SerializerMethodField() # define field

    class Meta:
        model = SocialPost

    def get_likes(self, obj):
        social_post_id = obj.id    
        # here write the logic to get the no. of likes 
        # for a social post using the 'social_post_id' from redis    
        return likes 

Now, the serialized data returned by DRF in list requests will contain a parameter likes along with other parameters.

Rahul Gupta
  • 46,769
  • 10
  • 112
  • 126
  • 1
    Thanks, it works great, I had edit my post to avoid "TypeError: b'1' is not JSON serializable" problem in this particular situation. – Windsooon May 03 '16 at 13:38
2

Maybe this is not the kind of answer you're looking for, but my suggestion would be to take a look at Cacheops.

It provides an automatic caching/invalidation mechanism for your django models, so you will not have to handle different lookups for redis and db in your code, just use the default django orm and in the background it will handle the memory caching for you. If you anyway store the likes both in db and redis, this is a better solution in my opinion.

sc3w
  • 1,154
  • 9
  • 21