将数据添加到Django REST Framework的ModelViewSet返回的列表中 [英] Add data to the list returned by Django REST Framework's 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屋!