Question :
I am working with Django for a first time and I’m trying to build an API and I am following some tutorials and examples and it works right, but I am running the project now in a Raspberry Pi after install all the requirements and the project is failing with the following error:
Performing system checks...
Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0xb547adb0>
Traceback (most recent call last):
File "/home/pi/.local/lib/python3.5/site-packages/django/utils/autoreload.py", line 225, in wrapper
fn(*args, **kwargs)
File "/home/pi/.local/lib/python3.5/site-packages/django/core/management/commands/runserver.py", line 120, in inner_run
self.check(display_num_errors=True)
File "/home/pi/.local/lib/python3.5/site-packages/django/core/management/base.py", line 364, in check
include_deployment_checks=include_deployment_checks,
File "/home/pi/.local/lib/python3.5/site-packages/django/core/management/base.py", line 351, in _run_checks
return checks.run_checks(**kwargs)
File "/home/pi/.local/lib/python3.5/site-packages/django/core/checks/registry.py", line 73, in run_checks
new_errors = check(app_configs=app_configs)
File "/home/pi/.local/lib/python3.5/site-packages/django/core/checks/urls.py", line 13, in check_url_config
return check_resolver(resolver)
File "/home/pi/.local/lib/python3.5/site-packages/django/core/checks/urls.py", line 23, in check_resolver
return check_method()
File "/home/pi/.local/lib/python3.5/site-packages/django/urls/resolvers.py", line 397, in check
for pattern in self.url_patterns:
File "/home/pi/.local/lib/python3.5/site-packages/django/utils/functional.py", line 36, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "/home/pi/.local/lib/python3.5/site-packages/django/urls/resolvers.py", line 536, in url_patterns
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
File "/home/pi/.local/lib/python3.5/site-packages/django/utils/functional.py", line 36, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "/home/pi/.local/lib/python3.5/site-packages/django/urls/resolvers.py", line 529, in urlconf_module
return import_module(self.urlconf_name)
File "/usr/lib/python3.5/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 986, in _gcd_import
File "<frozen importlib._bootstrap>", line 969, in _find_and_load
File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 673, in exec_module
File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
File "/home/pi/Projects/openvpn-monitor/openvpnmonitor/urls.py", line 24, in <module>
url(r'^api/', include('openvpnmonitor.api.urls')),
File "/home/pi/.local/lib/python3.5/site-packages/django/urls/conf.py", line 34, in include
urlconf_module = import_module(urlconf_module)
File "/usr/lib/python3.5/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 986, in _gcd_import
File "<frozen importlib._bootstrap>", line 969, in _find_and_load
File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 673, in exec_module
File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
File "/home/pi/Projects/openvpn-monitor/openvpnmonitor/api/urls.py", line 16, in <module>
urlpatterns += router.urls
File "/home/pi/.local/lib/python3.5/site-packages/rest_framework/routers.py", line 101, in urls
self._urls = self.get_urls()
File "/home/pi/.local/lib/python3.5/site-packages/rest_framework/routers.py", line 363, in get_urls
urls = super(DefaultRouter, self).get_urls()
File "/home/pi/.local/lib/python3.5/site-packages/rest_framework/routers.py", line 261, in get_urls
routes = self.get_routes(viewset)
File "/home/pi/.local/lib/python3.5/site-packages/rest_framework/routers.py", line 176, in get_routes
extra_actions = viewset.get_extra_actions()
AttributeError: type object 'SessionViewSet' has no attribute 'get_extra_actions'
My views.py has the following code:
from django.shortcuts import render
from rest_framework import viewsets
from .models import Session
from .serializers import SessionSerializer
from rest_framework.views import APIView, Response
class SessionViewSet(APIView):
queryset = Session.objects.all()
serializer_class = SessionSerializer
def get(self, request, format=None):
return Response("test")
I really don’t know why is working on my laptop but it is not working on my Raspberry Pi.
Has this happened to someone or anyone knows why is happening this?
Thank you so much!
Edit:
Here is my urls.py
from django.conf.urls import url
from rest_framework import routers
from openvpnmonitor.api.views import SessionViewSet
router = routers.DefaultRouter()
router.register(r'sessions', SessionViewSet)
urlpatterns = [
url(r'sessions', SessionViewSet.as_view()),
url(r'^docs/', schema_view),
]
urlpatterns += router.urls
Answer #1:
You’ve called it a viewset, but that doesn’t make it one; you inherit from APIView which is a standalone generic view, not a viewset.
A viewset needs to inherit from viewsets.ViewSet.
Answer #2:
Before Django Rest Framework v3.8 you could register an APIView
directly with a router. I did this extensively to gain a nice collated (and versioned) auto-documenting API for some very custom API endpoints. Given the choice again, I would probably write the whole thing a more standard way, but that isn’t an option for everybody.
But after digging into the error, it turns out you can just patch over the problem by giving the router what it wants and adding a dummy get_extra_actions
classmethod.
class MyAPIView(APIView):
@classmethod
def get_extra_actions(cls):
return []
#...
I’m not saying this is good, but it works for now.
I’ve got my documentation back and I’ve managed to upgrade to DRFv3.8.
Answer #3:
For:
djangorestframework==3.11.0
Django==2.2.9
You need to change class SessionViewSet(APIView):
to:
from rest_framework import mixins, viewsets
class SessionViewSet(mixins.ListModelMixin,
viewsets.GenericViewSet):
To get it to work. The internals of DRF have changed a bit and the other solutions won’t cut it any longer.
Answer #4:
In views.py, your viewset have to inherit from viewset and use it in your viewset try code below:
class SessionViewSet(viewsets.ModelViewSet):
queryset = Session.objects.all()
serializer_class = SessionSerializer
def get(self, request, format=None):
return Response("test")
Answer #5:
In my case, what I did was I inherited my view from viewsets.Viewset which is in rest_framework module and additionally, I added the basename = your_name argument in the router.register() function during registration.
The view would look something like:
class SessionViewSet(viewsets.ViewSet):
queryset = Session.objects.all()
serializer_class = SessionSerializer
def get(self, request, format=None):
return Response("test")
The router registeration would look something like:
router.register(r'your_app_name', YourModelNameView, basename='your_app_name')
Answer #6:
Beware of using the same names for your viewset class and your model class. This was the reason for my own error. See example of what i did
# inside member/views.py
from member.models import Member
# inheriting from model viewset but called Member
class Member(viewsets.ModelViewSet):
queryset = Member.objects.all()
...
# inside urls.py
from member.views import Member
router = routers.DefaultRouter()
router.register(r'member', Member)
Now the mistake here is its importing the member model instead of the viewset but they are of the same names