EN VI

Python - Using ViewSet, Generics and Mixin together in Django REST Framework?

2024-03-13 13:00:05
How to Python - Using ViewSet, Generics and Mixin together in Django REST Framework

I just started learning about DRF. We know that with generics and mixin Django REST Framework makes handling GET, POST, PUT, DELETE etc easy for users. And another feature is ViewSets. It helps us to achieve Don't Repeat Your code principle.

So, I have my old views.py file like this before:

class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

I updated my views.py like this:

class SnippetViewSet(viewsets.GenericViewSet, generics.ListCreateAPIView,
                     generics.RetrieveDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

i removed SnippetList and SnippetDetails (I don't know if its correct to do. But, in both of the classes we are repeating same code. So I thought with new SnippetViewSet I should delete both.)

Here is my urls.py :

from django.urls import path, include
from rest_framework.urlpatterns import format_suffix_patterns
from .views import SnippetViewSet, UserList, UserDetail
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('snippets', SnippetViewSet)

urlpatterns = [
    path('', include(router.urls))
]

urlpatterns = format_suffix_patterns(urlpatterns)

I am getting this error when I am running my application.

Traceback (most recent call last):
  File "C:\Users\mosleh\AppData\Local\Programs\Python\Python312\Lib\threading.py", line 1073, in _bootstrap_inner
    self.run()
  File "C:\Users\mosleh\AppData\Local\Programs\Python\Python312\Lib\threading.py", line 1010, in run
    self._target(*self._args, **self._kwargs)
  File "D:\Python Training\DRF\Tutorial\env\Lib\site-packages\django\utils\autoreload.py", line 64, in wrapper
    fn(*args, **kwargs)
  File "D:\Python Training\DRF\Tutorial\env\Lib\site-packages\django\core\management\commands\runserver.py", line 133, in inner_run
    self.check(display_num_errors=True)
  File "D:\Python Training\DRF\Tutorial\env\Lib\site-packages\django\core\management\base.py", line 486, in check
    all_issues = checks.run_checks(
                 ^^^^^^^^^^^^^^^^^^
  File "D:\Python Training\DRF\Tutorial\env\Lib\site-packages\django\core\checks\registry.py", line 88, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python Training\DRF\Tutorial\env\Lib\site-packages\django\core\checks\urls.py", line 14, in check_url_config
    return check_resolver(resolver)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Python Training\DRF\Tutorial\env\Lib\site-packages\django\core\checks\urls.py", line 24, in check_resolver
    return check_method()
           ^^^^^^^^^^^^^^
  File "D:\Python Training\DRF\Tutorial\env\Lib\site-packages\django\urls\resolvers.py", line 519, in check
    for pattern in self.url_patterns:
                   ^^^^^^^^^^^^^^^^^
  File "D:\Python Training\DRF\Tutorial\env\Lib\site-packages\django\utils\functional.py", line 47, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "D:\Python Training\DRF\Tutorial\env\Lib\site-packages\django\urls\resolvers.py", line 738, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
                       ^^^^^^^^^^^^^^^^^^^
  File "D:\Python Training\DRF\Tutorial\env\Lib\site-packages\django\utils\functional.py", line 47, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "D:\Python Training\DRF\Tutorial\env\Lib\site-packages\django\urls\resolvers.py", line 731, in urlconf_module
    return import_module(self.urlconf_name)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\mosleh\AppData\Local\Programs\Python\Python312\Lib\importlib\__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "D:\Python Training\DRF\Tutorial\tutorial\tutorial\urls.py", line 19, in <module>
    from snippets.views import SnippetList,SnippetDetail
ImportError: cannot import name 'SnippetList' from 'snippets.views' (D:\Python Training\DRF\Tutorial\tutorial\snippets\views.py). Did you mean: 'SnippetViewSet'?

I tried to use ViewSets and Generics together but cannot manage to do it. I am expecting to:

  1. See all my data when i go on /snippets and also able to post new snippet
  2. See detailed view when i browse /snippets/id and also options for putting and deleting.

Solution:

The problem is you are overriding Generic ViewSet and APIView together.

class SnippetViewSet(viewsets.GenericViewSet, generics.ListCreateAPIView,
    generics.RetrieveDestroyAPIView):
        queryset = Snippet.objects.all()
        serializer_class = SnippetSerializer

rather you could use mixins like this

class SnippetViewSet(viewsets.GenericViewSet,
                            mixins.ListModelMixin,
                            mixins.RetrieveModelMixin,):
        queryset = Snippet.objects.all()
        serializer_class = SnippetSerializer

also you can see documentation

Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login