Python/Django n00b moving over from javascript.
Trying to add an API endpoint using Django REST Framework which I'm hoping will ultimately be able to update a User with the body of a PATCH request, but for now I just want it to not throw a 500 error.
I've added this to urlpatterns:
url(r'update/$', views.UpdateView.as_view(), name="update_user"),
And that should bring in this view:
from django.contrib.auth.models import User
from rest_framework.generics import UpdateAPIView
from .serializers import UserSerializer
class UpdateView(UpdateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
The UserSerializer looks like this:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'pk', 'status')
Seem to be getting this every time I visit the route:
TypeError at /api/update/
'BasePermissionMetaclass' object is not iterable
I have no idea what I'm doing - anyone seen this before?
UPDATE: Full Traceback:
Internal Server Error: /api/update/
Traceback (most recent call last):
File "path/to/myapp/env/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "path/to/myapp/env/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "path/to/myapp/env/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "path/to/myapp/env/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "path/to/myapp/env/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "path/to/myapp/env/lib/python2.7/site-packages/rest_framework/views.py", line 495, in dispatch
response = self.handle_exception(exc)
File "path/to/myapp/env/lib/python2.7/site-packages/rest_framework/views.py", line 455, in handle_exception
self.raise_uncaught_exception(exc)
File "path/to/myapp/env/lib/python2.7/site-packages/rest_framework/views.py", line 483, in dispatch
self.initial(request, *args, **kwargs)
File "path/to/myapp/env/lib/python2.7/site-packages/rest_framework/views.py", line 401, in initial
self.check_permissions(request)
File "path/to/myapp/env/lib/python2.7/site-packages/rest_framework/views.py", line 333, in check_permissions
for permission in self.get_permissions():
File "path/to/myapp/env/lib/python2.7/site-packages/rest_framework/views.py", line 280, in get_permissions
return [permission() for permission in self.permission_classes]
TypeError: 'BasePermissionMetaclass' object is not iterable
You have mistyped the comma in DEFAULT_PERMISSION_CLASSES value, due to which Django takes it as a string, instead of a tuple.
Solution:
REST_FRAMEWORK = {
...
'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAdminUser', ),
...
}
I had the same problem, but looked for wrong place. I made mixin class with permissions and there was code
permission_classes = (
permissions.IsAuthenticated
)
but should be
permission_classes = (
permissions.IsAuthenticated,
# ^
# a comma here
)
So do not forget to look for other classes with permissions. I hope it will help someone.
As a reference for other people who might be searching here, this could be an issue too..
from django.contrib.auth.models import User
from rest_framework.generics import UpdateAPIView
from .serializers import UserSerializer
class UpdateView(UpdateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = IsAuthenticated
Should change to:
from django.contrib.auth.models import User
from rest_framework.generics import UpdateAPIView
from .serializers import UserSerializer
class UpdateView(UpdateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [IsAuthenticated]
#permission_classes((AllowAny,))
You have to ensure the comma
Junst in case this also can be solution. At least solved my issue
Just to complete #ihafurr's answer.
permission_classes shall be iterable because the variable is called by :func:viewsets.ModelViewSet.get_permission being (https://www.cdrf.co/3.12/rest_framework.viewsets/ModelViewSet.html):
def get_permissions(self):
return [permission() for permission in self.permission_classes]
Changing the last line of such method to the following could overcome the iterability requirement.
return [permission() for permission in self.permission_classes] if isinstance(self.permission_classes], Iterable) else [self.permission_classes]
where Iterable comes from
try:
from collections.abc import Iterable # for Python >= 3.6
except ImportError:
from collections import Iterable
I was facing the same problem and I was able to solve with this simple step
#permission_classes([IsAuthenticated])
so yeah, just put the method under the permission module in a bracket and you are good to go, hope it helps
Related
I'm trying to create a custom "list" under OptionViewSet but It's giving me an error.
class OptionViewSet(viewsets.ModelViewSet):
serializer_class = OptionSerializer
queryset = Option.objects.all()
def list(self, request):
queryset = Option.objects.all()
serializer = OptionSerializer(queryset, many=True)
return Response(serializer.data)
Error
__init__() takes 1 positional argument but 2 were given
This works fine:
class OptionViewSet(viewsets.ModelViewSet):
serializer_class = OptionSerializer
queryset = Option.objects.all()
urls.py
path('api/shipping/', include((shipping_routes.urls, 'shipping'), namespace='shipping')),
routes.py
routes.register(r'option', OptionViewSet, basename='option')
serializer
class OptionSerializer(serializers.ModelSerializer):
class Meta:
model = Option
fields = ['id', 'extra', 'name']
full traceback
Traceback (most recent call last):
File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\rest_framework\viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\rest_framework\views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
raise exc
File "C:\Users\Simon\.virtualenvs\django_backend-ZmgaAA1F\lib\site-packages\rest_framework\views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "C:\Users\Simon\Documents\GitHub\crud-react-django\django_backend\shipping\views.py", line 18, in list
return Response(serializer.data)
Exception Type: TypeError at /api/shipping/option/
Exception Value: __init__() takes 1 positional argument but 2 were given
I had the wrong Response import. Imported it from "requests" instead of "rest_framework.response".
In the url.py, in the the specific path from urlpatters[] you need to call your views.OptionViewSet.as_view() as a middle parameter between the URL path and the name reference:
path('api/shipping/', include((shipping_routes.urls, 'shipping'), namespace='shipping')),
Django has very good documentation and you can read more about the Django-Rest-Framework's ViewSets here:
https://www.django-rest-framework.org/api-guide/viewsets/
edit: From the exception stack trace we can see that url.py is refering to a problem with /api/shipping/option/ which essentially is the routes.py's record with basename='option'
Seems like you might need to adjust routes.py from
routes.register(r'option', OptionViewSet, basename='option')
to
routes.register(r'option', OptionViewSet.as_view(), basename='option')
Can you please give it a go and let us know how it goes!
To practice my Django skills i try to make simple module that should work more or less like Admin site in Django. It should gather all Models from Application, list them and show every object from each Model. i try to do is using Django Rest Framework.
Here is my views.py. I have 2 views. The api_root listens all models but it also sends params-models_names to another view 'model_view'. The ModelViewSet should list all objects from particular model.
class ModelsViewSet(viewsets.ModelViewSet):
def get_serializer(self, *args, **kwargs):
serializer_name = '{model_name}Serializer'.format(
model_name=self.kwargs.get('name').split(".")[1]
)
return getattr(serializers, serializer_name)
def get_model(self):
"""methods return model based on name kwargs
:return:
"""
return apps.get_model(self.kwargs.get('name'))
def get_queryset(self):
return self.get_model().objects.all()
def get_object(self):
return self.get_model().objects.get(pk=self.kwargs.get('pk'))
#api_view(['GET'])
def api_root(request, format=None):
return Response([reverse(
viewname='model_view',
kwargs={'name': i._meta.label}) for i in apps.get_models()])
Here is my serializers.py. In this file serializers classes are dynamically build. Each class is built on the basis of the model from django.apps.
from django.apps import apps
from rest_framework import serializers
from admin_site import serializers as m
from . import models
app_models = apps.get_models()
for item in app_models:
name = "{}Serializer".format(item.__name__)
class Meta(type):
model = item
fields = '__all__'
m.__dict__[name] = type(name, (serializers.ModelSerializer,), {})
m.__dict__[name].__metaclass__ = Meta
And finally here is my my_app.urls.py file. I think that maybe the problem is that ModelSetView isn't registered using DefaultRouter() but on the other hand i need to pass param to urlpattern. I don't know
urlpatterns = [
url(r'^$', views.api_root),
url(r'^model/(?P<name>[\w\-\.]+)/$',
views.ModelsViewSet.as_view({'get': 'list', 'put':'update'}), name='model_view'),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
Everything is fine when i'm on api_root, i can see list of models. But when i add to root url /model/auth.User/ i get this error:
Traceback (most recent call last):
File "/home/wojjak/Projects/envs/taskenvv/lib/python3.6/site-
packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/home/wojjak/Projects/envs/taskenvv/lib/python3.6/site-
packages/django/core/handlers/base.py", line 217, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/wojjak/Projects/envs/taskenvv/lib/python3.6/site-
packages/django/core/handlers/base.py", line 215, in _get_response
response = response.render()
File "/home/wojjak/Projects/envs/taskenvv/lib/python3.6/site-
packages/django/template/response.py", line 107, in render
self.content = self.rendered_content
File "/home/wojjak/Projects/envs/taskenvv/lib/python3.6/site-
packages/rest_framework/response.py", line 72, in rendered_content
ret = renderer.render(self.data, accepted_media_type, context)
File "/home/wojjak/Projects/envs/taskenvv/lib/python3.6/site-
packages/rest_framework/renderers.py", line 716, in render
context = self.get_context(data, accepted_media_type,
renderer_context)
File "/home/wojjak/Projects/envs/taskenvv/lib/python3.6/site-
packages/rest_framework/renderers.py", line 650, in get_context
raw_data_put_form = self.get_raw_data_form(data, view, 'PUT',
request)
File "/home/wojjak/Projects/envs/taskenvv/lib/python3.6/site-
packages/rest_framework/renderers.py", line 565, in get_raw_data_form
data = serializer.data.copy()
AttributeError: 'property' object has no attribute 'copy'
Any clue what can i do to accomplish my task and avoid this error?
override get_serializer_class() not get_serializer()
I am trying to make a notifications app. I have a middle that collects info about the action the user should be notified about and in the view that handles the action it automatically creates an instance in the UserNotification model. This is all working. Now, if a user's post gets liked by another user, that actions needs to be displayed on the notifications page. However, I obviously don't want any one use to be able to see every notification that is being created on the site, but rather only the notifications that are created by their posts.
I am running into an issue with the view and filtering the notifications based on the current user. More specifically, I am getting this error:
AttributeError at /notify/notify/
'UserNotifications' object has no attribute 'user'
With traceback:
Traceback (most recent call last):
File "/anaconda3/envs/dev/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/anaconda3/envs/dev/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/anaconda3/envs/dev/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/anaconda3/envs/dev/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/anaconda3/envs/dev/lib/python3.6/site-packages/django/contrib/auth/mixins.py", line 56, in dispatch
return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
File "/anaconda3/envs/dev/lib/python3.6/site-packages/django/views/generic/base.py", line 88, in dispatch
return handler(request, *args, **kwargs)
File "/anaconda3/envs/dev/lib/python3.6/site-packages/django/views/generic/list.py", line 160, in get
self.object_list = self.get_queryset()
File "/Users/garrettlove/Desktop/evverest/notify/views.py", line 30, in get_queryset
return UserNotification.objects.filter(user=request.user)
Here is my view pertaining to this:
// Bunch of imports are all here
User = get_user_model()
class UserNotifications(LoginRequiredMixin,ListView):
login_url = 'account_login'
model = UserNotification
template_name = 'notify/usernotification_list.html'
context_object_name = 'notifies'
paginate_by = 25
def get_queryset(request):
return UserNotification.objects.filter(user=request.user)
Here is my UserNotification model:
from django.db import models
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
User = get_user_model()
# Create your models here.
class UserNotification(models.Model):
user = models.ForeignKey(User,related_name='user',null=True)
post = models.ForeignKey('feed.UserPost',related_name='post')
timestamp = models.DateTimeField(auto_now_add=True)
notify_type = models.CharField(max_length=6)
read = models.BooleanField(default=False)
def __str__(self):
return str(self.user)
def get_queryset(self):
return UserNotification.objects.filter(user=self.request.user)
I'm practicing through the django rest_framework documentation and struck at authentication, especially token based authentication. I'm able to create token for user which already created. Now the thing is how to give permissions to users add, delete, update the information by providing the token. I have done some stuff, below
models.py
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)
highlighted = models.TextField(default = '')
class Meta:
ordering = ('created',)
views.py
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer,UserSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.contrib.auth.models import User
from rest_framework import generics
from rest_framework import permissions
from snippets.permissions import IsOwnerOrReadOnly
class SnippetList(APIView):
"""
List all snippets, or create a new snippet.
"""
def get(self, request, format=None):
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = SnippetSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly,)
class SnippetDetail(APIView):
"""
Retrieve, update or delete a snippet instance.
"""
# permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly,)
def get_object(self, pk):
try:
return Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
def put(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
snippet = self.get_object(pk)
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
class UserList(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
class UserDetail(generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
serializers.py
from rest_framework import serializers
from snippets.models import Snippet
from django.contrib.auth.models import User
class SnippetSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style','owner')
class UserSerializer(serializers.ModelSerializer):
snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())
#owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = User
fields = ('id', 'username', 'snippets')
permissions.py
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Custom permission to only allow owners of an object to edit it.
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
# Write permissions are only allowed to the owner of the snippet.
return obj.owner == request.user
ulrs.py
from django.conf.urls import url,include
from snippets import views
import rest_framework
#rfrom rest_framework.authtoken import views
urlpatterns = [
url(r'^snippets/$', views.SnippetList.as_view()),
url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()),
url(r'^api-token-auth/', rest_framework.authtoken.views.obtain_auth_token),
url(r'^users/$', views.UserList.as_view()),
url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),
url(r'^api-auth/', include('rest_framework.urls',
namespace='rest_framework')),
]
Error:
>>> from snippets.models import Snippet
>>> from snippets.serializers import SnippetSerializer
>>> from rest_framework.renderers import JSONRenderer
>>> from rest_framework.parsers import JSONParser
>>> snippet = Snippet(code='foo = "bar"\n')
>>> snippet.save()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/phygital/kiran/snippets/models.py", line 56, in save
super(Snippet, self).save(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 708, in save
force_update=force_update, update_fields=update_fields)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 736, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 820, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 859, in _do_insert
using=using, raw=raw)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 122, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 1039, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 1060, in execute_sql
cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/utils.py", line 95, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/sqlite3/base.py", line 323, in execute
return Database.Cursor.execute(self, query, params)
IntegrityError: NOT NULL constraint failed: snippets_snippet.owner_id
Token Authentication using Django rest framework.
views.py
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
class SampleView(APIView):
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAuthenticated,)
create Token for using in normal view or signal(post save method)
from rest_framework.authtoken.models import Token
token = Token.objects.create(user=your instance)
Pass the parameter as the Token in the Header of the request, as said in Django Rest Framework documentation:
For clients to authenticate, the token key should be included in the
Authorization HTTP header. The key should be prefixed by the string
literal "Token", with whitespace separating the two strings. For
example:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
While learning Django rest framework, I got a AssertionError at /tasks/1 error
Expected view TaskDetail to be called with a URL keyword argument named "pk". Fix your URL conf, or set the .lookup_field attribute on the view correctly.
My model.py
class Task(models.Model):
owner=models.ForeignKey('auth.User',related_name='tasks')
completed=models.BooleanField(default=False)
title=models.CharField(max_length=100)
description=models.TextField()
serializer.py
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
read_only=('owner.username',)
fields=('title','description','completed','owner.username')
permission.py
class IsOwnerOrReadOnly(BasePermission):
def has_object_permission(self, request, view, obj):
if request.method is SAFE_METHODS:
return True
return obj.owner==request.user
views.py
class TasksMixins(object):
queryset = Task.objects.all()
serializer_class=TaskSerializer
permission_classes=(IsOwnerOrReadOnly,)
def pre_save(self,obj):
obj.owner=self.request.user
class TaskList(TasksMixins,ListCreateAPIView):
pass
class TaskDetail(TasksMixins,RetrieveUpdateDestroyAPIView):
pass
Urls.py
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^tasks/$', views.TaskList.as_view(), name='task_list'),
url(r'^tasks/(?P<id>[0-9]+)$', views.TaskDetail.as_view(), name='task_detail')
]
Traceback
Traceback (most recent call last):
File "/home/amogh/PycharmProjects/env_1.9/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/home/amogh/PycharmProjects/env_1.9/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/amogh/PycharmProjects/env_1.9/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/home/amogh/PycharmProjects/env_1.9/local/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/amogh/PycharmProjects/env_1.9/local/lib/python2.7/site-packages/rest_framework/views.py", line 466, in dispatch
response = self.handle_exception(exc)
File "/home/amogh/PycharmProjects/env_1.9/local/lib/python2.7/site-packages/rest_framework/views.py", line 463, in dispatch
response = handler(request, *args, **kwargs)
File "/home/amogh/PycharmProjects/env_1.9/local/lib/python2.7/site-packages/rest_framework/generics.py", line 286, in get
return self.retrieve(request, *args, **kwargs)
File "/home/amogh/PycharmProjects/env_1.9/local/lib/python2.7/site-packages/rest_framework/mixins.py", line 56, in retrieve
instance = self.get_object()
File "/home/amogh/PycharmProjects/env_1.9/local/lib/python2.7/site-packages/rest_framework/generics.py", line 93, in get_object
(self.__class__.__name__, lookup_url_kwarg)
AssertionError: Expected view TaskDetail to be called with a URL keyword argument named "pk". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly.
When ever I navigate to the link I get this error
Any help is much appreciated...Thanks in advace
error image
If you want to target by 'pk', just rename id -> pk into your url.py:
url(r'^tasks/(?P<pk>[0-9]+)$', views.TaskDetail.as_view(), name='task_detail')
If you want to target by other field than pk,, you have to adjust the url.py, the view.py AND the serializer.py precising a lookup_field (that can be Nested) for example, it could be for you.
url.py:
url(r'^tasks/(?P<owner__username>[0-9]+)$', views.TaskDetail.as_view(), name='task_detail')
view.py:
class TasksMixins(object):
queryset = Task.objects.all()
serializer_class=TaskSerializer
permission_classes=(IsOwnerOrReadOnly,)
lookup_field = 'owner__username'
serializer.py
class TaskSerializer(serializers.ModelSerializer):
owner = serializers.SlugRelatedField(slug_field='username',many=False, read_only=True)
class Meta:
model = Task
fields='__all__'
lookup_field = 'owner__username'