我正在尝试通过当前授权用户的所有权来过滤API响应中的嵌套对象。
这是我的设置: Django 1.8,Django REST框架3。
class Container(models.Model):
container_title = models.CharField(max_length = 50)
class Item(models.Model):
item_title = models.CharField(max_length = 50, blank = True, null = True, default = " ")
item_container = models.ForeignKey(Container, on_delete = models.CASCADE, related_name = 'all_items_in_container')
class Notification(models.Model):
owner = models.ForeignKey('auth.User', null = True, on_delete = models.CASCADE)
item_to_track = models.ForeignKey(Container, default = False, blank = True, null = True, on_delete = models.CASCADE, related_name = 'notifications_for_container')
class ItemsSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Item
fields = ('pk', 'item_title')
class NotificationSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.IntegerField(source='owner.pk')
class Meta:
model = Notification
fields = ('pk', 'owner')
class ContainerSerializer(serializers.ModelSerializer):
all_items_in_container = ItemsSerializer(many=True)
#notifications_for_container = NotificationSerializer(many = True) # this line returns all existing notifications per Container
notifications_for_container = serializers.SerializerMethodField('get_current_user_notifications')
def get_current_user_notifications(self, obj):
user = self.context['request'].user
user_notifications = Notification.objects.filter(item_to_track=obj, owner=user)
serializer = NotificationSerializer(user_notifications)
return serializer.data
class Meta:
model = Container
fields = ('notifications_for_container', 'pk', 'container_title', 'all_items_in_container')
class ContainerViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Container.objects.all()
def list(self, request, *args, **kwargs):
queryset = self.queryset
serializer = ContainerSerializer(data = [], many = True, context={'request': request})
if serializer.is_valid():
new_serializer = ContainerSerializer(queryset, many = True, context={'request': request})
data = new_serializer.data[:]
return Response({'data':data})
def retrieve(self, request, pk, *args, **kwargs):
queryset = self.get_queryset()
try:
holder = Container.objects.get(pk=pk)
except Container.DoesNotExist:
holder = False
if holder:
serializer = ContainerSerializer(holder, context={'request': request})
data = serializer.data
return Response({'data':data})
不同的用户可以为同一个Container创建Notification对象。
如果我取消注释#notifications_for_container = NotificationSerializer(many = True)
,我会得到:
"data": [
{
"notifications_for_container": [
{
"pk": 11,
"owner": 2,
},
{
"pk": 20,
"owner": 46,
}
],
"pk": 6,
"container_title": "TEST CONTAINER",
"all_items_in_holder": [
{
"pk": 12,
"item_title": "xbox1 from amazon ",
},
]
}
]
无论我当前登录的是哪个用户。
我在此尝试实现的目标是仅在API响应的notifications_for_container
部分中返回所有者的通知。
例如,如果我以pk=2
用户身份登录,我应该只获得
"data": [
{
"notifications_for_container": [
{
"pk": 11,
"owner": 2,
}
]
...
...
我一直在尝试从How can I apply a filter to a nested resource in Django REST framework?实施解决方案,但我得到KeyError at /api/containers/ 'request'
我已经尝试解决这个问题2天了,也许我没有看到明显的东西,所以任何帮助都会受到赞赏。 提前谢谢!
答案 0 :(得分:0)
您的代码的问题似乎是context
属性没有填充当前请求。看看Including extra context。可能你应该做的事情如下:
serializer = ContainerSerializer(many=True, context={'request': request})
答案 1 :(得分:0)
第一
serializer = ContainerSerializer(many=True, context={'request': request})
或
serializer = ContainerSerializer(many=True, context=self.get_serializer_context())
第二
def get_current_user_notifications(self, obj):
user = self.context['request'].user
# user_notifications is a queryset
user_notifications = Notification.objects.filter(item_to_track=obj, owner=user)
# so you need add many=True
serializer = NotificationSerializer(user_notifications, many=True)
return serializer.data