我有两个模型:Foo带有一个所有者字段,而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对象。
答案 0 :(得分: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