3

Lets say i have a ToDo Model like this:

class ToDo(models.Model):
    user = models.ForeignKey(UserModel)
    text = models.CharField(max_length=255, blank=True)

And i'm using django rest framework for my API. Then i'll have this for the serializer:

class ToDoSerializer(serializers.ModelSerializer):
    class Meta:
        model = ToDo
        fields = ('text', 'id', 'user')

and this for the ViewSet:

class ToDoResponder(viewsets.ModelViewSet):
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)
    model = ToDo
    def get_queryset(self):
        return ToDo.objects.filter(user=self.request.user)
    serializer_class = ToDoSerializer

As i'm using TokenAuthentication and get_queryset() the user can only see his own Todos. Unfortunately i can send ToDos and fake the user field so i could spam the ToDo List of another user. I don't want that.

How can i tell django-rest-framework to use request.user for specific fields like 'user' in the most DRY/Pythonic way? After all this is no exotic requirement and should be reused.

Thanks

Harper04
  • 355
  • 2
  • 10

1 Answers1

2

In the drf doc http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions you can find a solution creating a new permission:

from rest_framework import permissions


class IsOwner(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        return obj.user == request.user

at this point you can use it in your ToDoResponder

permission_classes = (IsAuthenticated, IsOwner)

In the same page in your ToDoResponder:

def pre_save(self, obj):
    obj.user = self.request.user
    super(ToDoResponder, self).pre_save(obj)
Andrea de Marco
  • 827
  • 5
  • 9
  • Thanks that should work but i am still looking for another solution since i'd like to use `request.user` as the default value for `user` so the client don't has to send the user id. – Harper04 Jan 13 '14 at 15:25
  • Exactly what i want! One note: i had to remove 'user' from the fields list in the serializer otherwise pre_save() will not be called – Harper04 Jan 13 '14 at 16:08
  • You could add `editable=False` to `user = models.ForeignKey(UserModel)` if a ToDo Entry can't change the owner – Andrea de Marco Jan 13 '14 at 16:11
  • that does not work for me. neither for this guy https://groups.google.com/forum/#!topic/django-rest-framework/jjBuuImMADw – Harper04 Jan 13 '14 at 16:13
  • Did you try with `user = models.ForeignKey(UserModel, blank=True)`? – Andrea de Marco Jan 13 '14 at 16:43
  • Leads to ValueError: Cannot assign None: "ToDo.user" does not allow null values. But i would consider changing it to blank=True or null=True bad practice because the model needs a valid user from the datastructure point of view – Harper04 Jan 13 '14 at 16:52