【问题标题】:Django Rest Framework: Filter/Validate Related FieldsDjango Rest Framework:过滤/验证相关字段
【发布时间】:2016-09-06 06:31:04
【问题描述】:

我有两个模型:Foo 带有 owner 字段,Bar 与 Foo 有关系:

class Foo(models.Model):
    owner = models.ForeignKey('auth.User')  
    name = models.CharField(max_length=20, null=True)

class Bar(models.Model):
    foo = models.OneToOneField(Foo, related_name='bar')
    [...]

我使用 HyperlinkedModelSerializer 来表示:

class BarSerializer(serializers.HyperlinkedModelSerializer): 
    foo = serializers.HyperlinkedRelatedField(view_name='foo-detail', queryset=Foo.objects.all())
    [...]

    class Meta:
        model = Bar
        fields = ('foo', [...])

class FooSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.SlugRelatedField(read_only=True, slug_field='username')
    bar = serializers.HyperlinkedRelatedField(view_name='bar-detail', read_only=True)

    class Meta:
        model = Foo
        fields = ('name', 'bar', 'owner')

我的观点是这样的:

class FooViewSet(viewsets.ModelViewSet):
    queryset = Foo.objects.all()
    serializer_class = FooSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwner,)

    def get_queryset(self):
        user = self.request.user

        if not user.is_authenticated():
            return Foo.objects.none()

        if user.username == "admin":
            return Foo.objects.all()

        return Foo.objects.filter(owner=user)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

class BarViewSet(viewsets.ModelViewSet):
    queryset = Bar.objects.all()
    serializer_class = BarSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwner,)

    def get_queryset(self):
        user = self.request.user

        if not user.is_authenticated():
            return Bar.objects.none()

        if user.username == "admin":
            return Bar.objects.all()

        return Bar.objects.filter(foo__owner=user)

我不希望用户 A 能够看到用户 B 的内容,反之亦然。到目前为止效果很好,但有一个例外:

用户 A 创建了 Foo 的实例,但没有立即创建链接到 Foo 的 Bar 实例。现在用户 B 可以猜测用户 A 的 Foo 实例的 URL,并在创建他的 Bar 实例时指定它。

此时,用户 A 获得了一个并非他创建的 Bar 实例。

我是 Django 和 rest_framework 的新手,所以我不知道如何解决这个问题。有人可以让我走上正轨吗?我的第一个想法是使用 BarSerializer 中的 foo 字段来使用查询集过滤 Foos。但我不知道如何从那里访问 auth.User 对象。

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    如果您include it in its context,您可以在序列化程序中访问请求。 然后你可以在 Bar 序列化器里面做field level validation

    def validate_foo(self, val):
        user = self.context['request'].user
    
        try:
            foo = Foo.objects.get(pk=val)
        except Foo.DoesNotExist:
            raise serializers.ValidationError("Some Error")
    
        if foo.user is not user:
            raise serializers.ValidationError("Some Error")
    
       return value
    

    【讨论】:

    猜你喜欢
    • 2018-04-12
    • 2018-10-03
    • 2018-08-07
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-13
    • 2018-05-17
    相关资源
    最近更新 更多