web-dev-qa-db-fra.com

Django viewset n'a pas d'attribut 'get_extra_actions'

Je travaille avec Django pour la première fois et j'essaye de construire une API et je suis quelques tutoriels et exemples et ça marche bien, mais j'exécute le projet maintenant dans une framboise Pi après avoir installé toutes les exigences et le projet échoue avec l'erreur suivante:

    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'

Mon views.py a le code suivant:

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")

Je ne sais vraiment pas pourquoi travaille sur mon ordinateur portable mais cela ne fonctionne pas sur mon Raspberry Pi.

Est-ce arrivé à quelqu'un ou quelqu'un sait pourquoi cela se produit?

Merci beaucoup!

Éditer:

Voici mes 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
23
alexca

Vous l'avez appelé un ensemble de vues, mais cela n'en fait pas un; vous héritez d'APIView qui est une vue générique autonome, pas un ensemble de vues.

Un ensemble de vues doit hériter des ensembles de vues.ViewSet.

31
Daniel Roseman

Avant Django Rest Framework v3.8 vous pourriez enregistrer un APIView directement avec un routeur. J'ai fait cela de manière approfondie pour obtenir un Nice assemblé (et versionné) ) API d'auto-documentation pour certains très points de terminaison d'API personnalisés. Si c'était à refaire, j'écrirais probablement le tout de manière plus standard, mais ce n'est pas une option pour tout le monde.

Mais après avoir creusé l'erreur, il s'avère que vous pouvez simplement corriger le problème en donnant au routeur ce qu'il veut et en ajoutant un mannequin get_extra_actions méthode de classe.

class MyAPIView(APIView):

    @classmethod
    def get_extra_actions(cls):
        return []

#...

Je ne dis pas que c'est bon, mais ça marche pour l'instant.
J'ai récupéré ma documentation et j'ai réussi à passer à DRFv3.8.

14
Oli

Dans views.py, votre ensemble de vues doit hériter de l'ensemble de vues et l'utiliser dans votre code d'essai d'ensemble de vues ci-dessous:

class SessionViewSet(viewsets.ModelViewSet):
    queryset = Session.objects.all()
    serializer_class = SessionSerializer

    def get(self, request, format=None):
        return Response("test")
3
Ehsan Ahmadi

Pour:

djangorestframework==3.11.0
Django==2.2.9

Vous devez remplacer class SessionViewSet(APIView): par:

from rest_framework import mixins, viewsets

class SessionViewSet(mixins.ListModelMixin,
                     viewsets.GenericViewSet):

Pour le faire fonctionner. Les internes de DRF ont un peu changé et les autres solutions ne le couperont plus.

2
boatcoder

Dans mon cas, ce que j'ai fait, c'est que j'ai hérité ma vue de viewsets.Viewset qui est dans le module rest_framework et en plus, j'ai ajouté l'argument basename = your_name dans la fonction router.register () lors de l'enregistrement.

La vue ressemblerait à quelque chose comme:

class SessionViewSet(viewsets.Viewset):
    queryset = Session.objects.all()
    serializer_class = SessionSerializer

    def get(self, request, format=None):
        return Response("test")

L'enregistrement du routeur ressemblerait à quelque chose comme:

router.register(r'your_app_name', YourModelNameView, basename='your_app_name')
1
Varun Sharma