我在StorySerializer中的GET /api/stories/169/
上收到以下错误,如下注释所示:
AttributeError at /api/stories/169/
'ManyRelatedField' object has no attribute 'queryset'
在检查物体时,我发现如果我把线从。。。
fields['feature'].queryset = fields['feature'].queryset.filter(user=user)
至
fields['photos'].child_relation.queryset = fields['photos'].child_relation.queryset.filter(user=user)
这似乎奏效了。但这种方法没有记录在案,我确信这不是正确的方法
我有这些型号:
class Story(CommonInfo):
user = models.ForeignKey(User)
text = models.TextField(max_length=5000,blank=True)
feature = models.ForeignKey("Feature", blank=True, null=True)
tags = models.ManyToManyField("Tag")
class Feature(CommonInfo):
user = models.ForeignKey(User)
name = models.CharField(max_length=50)
class Photo(CommonInfo):
user = models.ForeignKey(User)
image = ImageField(upload_to='photos')
story = models.ForeignKey("Story", blank=True, null=True, related_name='photos', on_delete=models.SET_NULL)
和一个StorySerializer
:
class StorySerializer(serializers.HyperlinkedModelSerializer):
user = serializers.CharField(read_only=True)
comments = serializers.HyperlinkedRelatedField(read_only=True, view_name='comment-detail', many=True)
def get_fields(self, *args, **kwargs):
user = self.context['request'].user
fields = super(StorySerializer, self).get_fields(*args, **kwargs)
## Restrict the options that the user can pick to the Features
## and Photos that they own
# This line works:
fields['feature'].queryset = fields['feature'].queryset.filter(user=user)
# This line throws the error:
fields['photos'].queryset = fields['photos'].queryset.filter(user=user)
return fields
class Meta:
model = Story
fields = ('url', 'user', 'text', 'comments', 'photos', 'feature', 'tags')
我做错了什么?我觉得这与ForeignKey
关系的方向有关。
两个要点。
-
当从用户的视图中筛选查询集时,所有外键对象检索将只生成特定用户的对象。因此不需要为
get_fields
内部的用户进行筛选。class StoryList(generics.ListAPIView): serializer_class = StorySerializer def get_queryset(self): # consider there is login check before code is reaching here # since this filtered by the user and any susbquent # foreign key objects will belong only to this user return Story.objects.filter(user=self.request.user)
-
一旦对用户进行了筛选,就可以使用另一个序列化程序或
SerializerMethodField
来相应地构建数据。下面的代码应该适用于您的案例。class UserSerializer(serializers.HyperlinkedModelSerializer): class Meta: # Allow only url and id fields = ['id', 'url'] extra_kwargs = {'url': {'view_name': 'user-detail'}} class FeatureSerializer(serializers.HyperlinkedModelSerializer): class Meta: fields = ['id', 'url'] extra_kwargs = {'url': {'view_name': 'feature-detail'}} class PhotoSerializer(serializers.HyperlinkedModelSerializer): class Meta: fields = ['id', 'url'] extra_kwargs = {'url': {'view_name': 'photo-detail'}} class StorySerializer(serializers.HyperlinkedModelSerializer): user = UserSerializer(read_only=True) comments = serializers.HyperlinkedRelatedField(read_only=True, view_name='comment-detail', many=True) # this work because of related names features = FeatureSerializers(many=True) photos = PhotoSerializers(many=True) # add tags serializer as well text = serializers.CharField() class Meta: fields = ['id', 'users', 'photos', 'features', ...]
您可以使用django滤波器
我认为编辑get in serializer 是不实用的解决方案
您可以尝试drf可写嵌套包,而不是覆盖get_fields方法,这将有助于更容易地序列化嵌套关系,并更好地掌握表单字段的方向。