Following this tutorial:
http://django-rest-framework.org/tutorial/1-serialization.html
through http://django-rest-framework.org/tutorial/4-authentication-and-permissions.html
I have this code:
# models.py
class Message(BaseDate):
"""
Private Message Model
Handles private messages between users
"""
status = models.SmallIntegerField(_('status'), choices=choicify(MESSAGE_STATUS))
from_user = models.ForeignKey(User, verbose_name=_('from'), related_name='messages_sent')
to_user = models.ForeignKey(User, verbose_name=_('to'), related_name='messages_received')
text = models.TextField(_('text'))
viewed_on = models.DateTimeField(_('viewed on'), blank=True, null=True)
# serialisers.py
class MessageSerializer(serializers.ModelSerializer):
from_user = serializers.Field(source='from_user.username')
to_user = serializers.Field(source='to_user.username')
class Meta:
model = Message
fields = ('id', 'status', 'from_user', 'to_user', 'text', 'viewed_on')
# views.py
from permissions import IsOwner
class MessageDetail(generics.RetrieveUpdateDestroyAPIView):
model = Message
serializer_class = MessageSerializer
authentication_classes = (TokenAuthentication, SessionAuthentication)
permission_classes = (permissions.IsAuthenticated, IsOwner)
# permissions.py
class IsOwner(permissions.BasePermission):
"""
Custom permission to only allow owners of an object to edit or delete it.
"""
def has_permission(self, request, view, obj=None):
# Write permissions are only allowed to the owner of the snippet
return obj.from_user == request.user
# urls.py
urlpatterns = patterns('',
url(r'^messages/(?P<pk>[0-9]+)/$', MessageDetail.as_view(), name='api_message_detail'),
)
Then opening the URL of the API i get this error:
**AttributeError at /api/v1/messages/1/
'NoneType' object has no attribute 'from_user'**
Traceback:
File "/var/www/sharigo/python/lib/python2.6/site-packages/django/core/handlers/base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "/var/www/sharigo/python/lib/python2.6/site-packages/django/views/generic/base.py" in view
48. return self.dispatch(request, *args, **kwargs)
File "/var/www/sharigo/python/lib/python2.6/site-packages/django/views/decorators/csrf.py" in wrapped_view
77. return view_func(*args, **kwargs)
File "/var/www/sharigo/python/lib/python2.6/site-packages/rest_framework/views.py" in dispatch
363. response = self.handle_exception(exc)
File "/var/www/sharigo/python/lib/python2.6/site-packages/rest_framework/views.py" in dispatch
351. self.initial(request, *args, **kwargs)
File "/var/www/sharigo/python/lib/python2.6/site-packages/rest_framework/views.py" in initial
287. if not self.has_permission(request):
File "/var/www/sharigo/python/lib/python2.6/site-packages/rest_framework/views.py" in has_permission
254. if not permission.has_permission(request, self, obj):
File "/var/www/sharigo/sharigo/apps/sociable/permissions.py" in has_permission
17. return obj.from_user == request.user
Exception Type: AttributeError at /api/v1/messages/1/
Exception Value: 'NoneType' object has no attribute 'from_user'
It seems like None is being passed as the value for the parameter "obj" to isOwner.has_permission(). What am I doing wrong? I think i followed strictly the tutorial.
When has_permission()
is called with obj=None
it's supposed to return whether the user has permission to any object of this type. So you should handle the case when None is passed.
Your code should be something like:
def has_permission(self, request, view, obj=None):
# Write permissions are only allowed to the owner of the snippet
return obj is None or obj.from_user == request.user
Use function has_object_permission
instead of has_permission
.
ex:
def has_object_permission(self, request, view, obj=None):
return obj.from_user == request.user
and call function check_object_permissions
inside get_object in views
def get_object(self):
obj = get_object_or_404(self.get_queryset())
self.check_object_permissions(self.request, obj)
return obj
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With