在我的应用程序中,我有以下模型:
class Zone(models.Model):
name = models.SlugField()
class ZonePermission(models.Model):
zone = models.ForeignKey('Zone')
user = models.ForeignKey(User)
is_administrator = models.BooleanField()
is_active = models.BooleanField()
我正在使用Django REST框架来创建一个返回区域详细信息的资源,以及一个显示该区域的经过身份验证的用户权限的嵌套资源 . 输出应该是这样的:
{
"name": "test",
"current_user_zone_permission": {
"is_administrator": true,
"is_active": true
}
}
我已经创建了这样的序列化器:
class ZonePermissionSerializer(serializers.ModelSerializer):
class Meta:
model = ZonePermission
fields = ('is_administrator', 'is_active')
class ZoneSerializer(serializers.HyperlinkedModelSerializer):
current_user_zone_permission = ZonePermissionSerializer(source='zonepermission_set')
class Meta:
model = Zone
fields = ('name', 'current_user_zone_permission')
这样做的问题是,当我请求特定区域时,嵌套资源会为具有该区域权限的用户返回 all 的ZonePermission记录 . 有没有办法将 request.user
上的过滤器应用于嵌套资源?
顺便说一下,我不想使用 HyperlinkedIdentityField
(最小化http请求) .
解决方案
这是我根据下面的答案实现的解决方案 . 我将以下代码添加到我的序列化程序类:
current_user_zone_permission = serializers.SerializerMethodField('get_user_zone_permission')
def get_user_zone_permission(self, obj):
user = self.context['request'].user
zone_permission = ZonePermission.objects.get(zone=obj, user=user)
serializer = ZonePermissionSerializer(zone_permission)
return serializer.data
非常感谢您的解决方案!
5 回答
我发现'm faced with the same scenario. The best solution that I'是使用
SerializerMethodField
并使用该方法查询并返回所需的值 . 您可以通过self.context['request'].user
访问该方法中的request.user
.不过,这似乎有点像黑客 . 我对DRF很新,所以也许有经验丰富的人可以加入 .
您必须使用filter而不是get,否则如果多个记录返回,您将获得Exception .
现在你可以使用我在这里描述的方法继承ListSerializer:https://stackoverflow.com/a/28354281/3246023
如果你在多个地方使用QuerySet /过滤器,你可以 use a getter function on your model ,然后甚至删除序列化器/字段的'source' kwarg . DRF automatically calls functions/callables if it finds them 使用它时get_attribute功能 .
我喜欢这种方法,因为它通过HTTP上的api保持API的一致性 .
希望这有助于一些人!
注意:名称不匹配 need ,如果需要/你想仍然可以使用源kwarg .
编辑:我刚刚意识到模型上的函数无法访问用户或请求 . 因此,自定义模型字段/ ListSerializer可能更适合此任务 .
我会用两种方式之一来做 .
1)通过视图中的预取来执行此操作:
2)或者通过.to_代表来做: