2016-09-06 106 views
2

我有两个型号:美孚携带所有者场和酒吧具有相对富:Django的REST框架:过滤器/验证相关领域

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) 

我不whant用户A可以看到用户B的东西,反之亦然。目前为止,该方法运行良好,只有一个例外:

用户A创建了Foo的实例,但并未立即创建链接到Foo的Bar实例。现在,用户B可以猜测用户A的Foo实例的URL,并指定创建其实例的Bar时的情况。

此时,用户A获取他没有创建的Bar实例。

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

回答

0

如果你使用include it in its context,你可以访问Serializer中的请求。 然后你可以在里面的Bar序列化程序:

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