Reputation: 31
I have two models: Foo which carries an owner field and Bar which has a relation to 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')
[...]
I use HyperlinkedModelSerializer for representation:
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')
My views look like this:
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)
I don't whant User A to be able to see User B's stuff and vice versa. That works pretty well so far with one exception:
User A created an instance of Foo but doesn't instantly create an instance of Bar linking to Foo. Now User B can guess the URL to User A's Foo instance and specify that when creating his instance of Bar.
At this point, User A gets an instance of Bar which he didn't create.
I'm new to Django and rest_framework, so I have no idea how to solve this. Can somebody get me on the right track? My first idea was to use the foo field in BarSerializer to filter Foos using the queryset. But I didn't figure out how to get access to the auth.User object from there.
Upvotes: 3
Views: 2014
Reputation: 9446
You can access the request inside a Serializer if you include it in its context. Then you can do field level validation inside the Bar serializer:
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
Upvotes: 2