将数据添加到Django REST Framework的ModelViewSet返回的列表中 [英] Add data to the list returned by Django REST Framework's ModelViewSet

查看:147
本文介绍了将数据添加到Django REST Framework的ModelViewSet返回的列表中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以将自定义数据添加到使用Django REST Framework的ModelViewSet的视图的列表API调用返回的结果数据中?

Is there a way to add custom data to the results data returned by a list API call to a view that uses Django REST Framework's ModelViewSet?

我的ModelViewSet视图是

My ModelViewSet view is attached to an Items model.

除了由LIST API调用返回的项目列表外,我还想查询一个单独的Seen模型并返回,每个项目被查看的次数。

In addition to the list of Items that is returned by the LIST API call I want to query a separate Seen model and return, with the Items, the number of times each Item has been seen.

我还想在返回的数据中添加每日报价。

I also want to add a 'Quote of the day' to the returned data.

我已经搜索了DRF文档,却找不到任何提及方法。

I have searched the DRF documentation and haven't been able to find any mention of how to do this.

这是我的代码。 Item序列化程序为:

Here is my code. The Item serializer is:

class ItemSerializer(serializers.ModelSerializer):
    username = serializers.SerializerMethodField()

    def get_username(self, obj):
        """
        Note that query params can be accessed here as follows:
        request = self.context['request']
        print request.query_params.get['fields']
        """
        value = str(obj.owner)
        return value

    def get_keywords(self, obj):
        value = str(obj.keywords)
        return value

    class Meta:
        model = Item
        fields = ('id', 'url', 'item_type', 'title', 'credits_applied', 'credits_left', 'credits_gifted', 'username', 'liked', 'disliked')

视图如下:

class ItemViewSet(viewsets.ModelViewSet):
    queryset = Item.objects.all().order_by('-date_added')
    serializer_class = ItemSerializer

    # When POSTing (creating) a new item add appropriate User instance to the serializer
    def perform_create(self, serializer):
        creator = User.objects.get(pk=self.request.data['owner_id'])
        serializer.save(owner=creator)

     def get_queryset(self):
        this_user = self.request.query_params.get('user', None)
        restrict_to_items_from_user_id = self.request.query_params.get('from', None)
        quantity = self.request.query_params.get('num', 20)

        # Use query params to determine what to return

        if restrict_to_items_from_user_id is not None:
            # API: /api/items/from=<id>
            # Return items owned by a specific user. Used by someone to get a list of the items they have added

            queryset = Item.objects.filter(owner=restrict_to_items_from_user_id, active=True).order_by('-date_added')[0:int(quantity)]

        elif this_user is not None:
            # API: /api/items/user=<id>
            # Return unseen items for the given user's browse feed

            # queryset = Item.objects.all().order_by('-date_added')[0:int(quantity)]
            queryset = Item.objects.filter(active=True, credits_left__gt=0).exclude(pk__in=Seen.objects.filter(user_id=this_user).values_list('item_id', flat=True))[0:int(quantity)]

        # :TO DO: Add option to list the items a user has liked!

        else:
            # API: /api/items
            # Return items not specific to a particular user (used for testing the app or when user wants to see stuff they have seen before)

            queryset = Item.objects.filter(active=True, credits_left__gt=0)[0:int(quantity)]

        return queryset

The项目和可见模型为:

The Item and Seen models are:

class Item(models.Model):

    ITEM_TYPES = (
        ('V', 'Vine'),
        ('Y', 'YouTube'),
        ('P', 'Photo'),         # Photo is stored by us on a CDN somewhere
        ('F', 'Flickr'),
        ('I', 'Instagram'),
        ('D', 'DeviantArt'),
        ('5', '500px'),
    )
    owner           = models.ForeignKey(User, on_delete=models.CASCADE)     # Id of user who owns the item
    title           = models.CharField(max_length=60, default='')           # URL of where item resides (e.g. Vine or YouTube url)
    url             = models.CharField(max_length=250, default='', unique=True)
                                                                            # URL of where item resides (e.g. Vine or YouTube url)
    item_type       = models.CharField(max_length=1, choices=ITEM_TYPES)    # Type of item (e.g. Vine|YoutTube|Instagram|etc.)
    keywords        = models.ManyToManyField(Keyword, related_name='keywords')
                                                                            # E.g. Art, Travel, Food, etc.
    credits_applied = models.IntegerField(default=10, help_text='Total number of credits applied to this item including any given by VeeU admin')
                                                                            # Records the total number of credits applied to the Item
    credits_left    = models.IntegerField(default=10, help_text='The number of credits still remaining to show the item')
                                                                            # Number of credits left (goes down each time item is viewed
    credits_gifted  = models.IntegerField(default=0, help_text='The number of credits this item has been gifted by other users')
                                                                            # Number of credits users have gifted to this item
    date_added      = models.DateTimeField(auto_now_add=True)               # When item was added
    liked           = models.IntegerField(default=0)                        # Number of times this item has been liked
    disliked        = models.IntegerField(default=0)                        # Number of times this item has been disliked
    active          = models.BooleanField(default=True, help_text='If you mark this item inactive please say why in the comment field. E.g. "Inapproriate content"')
                                                                            # True if item is available for showing
    comment         = models.CharField(max_length=100, blank=True)          # Comment to be applied if item is inactive to say why

    # Add defs here for model related functions

    # This to allow url to be a clickable link
    def item_url(self):
        return u'<a href="%s">%s</a>' % (self.url, self.url)
    item_url.allow_tags = True

    def __str__(self):
        return '%s: Title: %s, URL: %s' % (self.owner, self.title, self.url)

# Record of which items have been viewed, when, and whether they were liked or not
class Seen(models.Model):
    item_seen           = models.ForeignKey(Item, on_delete=models.CASCADE)     # id of the item that has been seen
    who_saw             = models.ForeignKey(User, on_delete=models.CASCADE)     # id of user who viewed it
    date_seen           = models.DateTimeField(auto_now_add=True)               # When item was viewed
    liked               = models.BooleanField(help_text='If the item was liked this is set to true')

    class Meta:
        unique_together = ('item_seen', 'who_saw',)

推荐答案

如果要将新数据附加到常规响应中,则可以可以做到这一点:

If you want to attach the new data to the regular response, you can do this:

class ItemViewSet(viewsets.ModelViewSet):
    ...

    def list(self, request, *args, **kwargs):
        custom_data = {
            'list_of_items': ItemSerializer(self.get_queryset(),many=true).data  # this is the default result you are getting today
            'quote_of_the_day': <code to compute Quote of the day>
            'number_of_times': <code to compute number of times>
        }
        return Response(custom_data)
    ...

不过,根据您的评论来判断:看到每个项目的次数。时间长度看起来像是每个项目的新属性,因此您也可以执行以下操作:

although, and judging by your comment: "the number of times each Item has been seen." the number of time looks like it is a new property for each item, so you also can do:

class ItemViewSet(viewsets.ModelViewSet):
    ...

    def list(self, request, *args, **kwargs):
        custom_data = {
        'list_of_items': ItemSerializer(self.get_queryset(), many=true).data  # this is the default result you are getting today
         'quote_of_the_day': <code to compute Quote of the day>
        })
        return Response(custom_data)
...

class ItemSerializer(serializers.ModelSerializer):
    ...
    number_of_times = serializers.SerializerMethodField()
    ...

    def get_number_of_times(self):
        # compute and return the number of times the Item has been seen.
    ...

这篇关于将数据添加到Django REST Framework的ModelViewSet返回的列表中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆