Как реализовать все методы CRUD в одном представлении на основе классов во фреймворке Django

Всем доброго дня. После бесчисленных попыток решить свою проблему, я решил обратиться сюда за советом. Я пишу небольшое приложение с двумя моделями: Departments и Employees. И я решил переписать все функциональные представления в представления на основе классов. С помощью REST-фреймворка Django мне удалось реализовать следующее решение: Это drf-api-view.py:

from django.core.cache import cache
from rest_framework.generics import ListAPIView,  CreateAPIView, RetrieveUpdateDestroyAPIView
from rest_framework.exceptions import ValidationError
from rest_framework.pagination import LimitOffsetPagination
from django_filters.rest_framework import DjangoFilterBackend
from department.models.models import Department, Employee
from department.rest.serializers import DepartmentSerializer, EmployeeSerializer


class DepartmentPagination(LimitOffsetPagination):
    default_limit = 10
    max_limit = 100

class EmployeePagination(LimitOffsetPagination):
    default_limit = 10
    max_limit = 100

class DepartmentView(ListAPIView, CreateAPIView, RetrieveUpdateDestroyAPIView):
    queryset = Department.objects.all().order_by('title')
    serializer_class = DepartmentSerializer
    filter_backends = (DjangoFilterBackend,)
    pagination_class = DepartmentPagination
    lookup_field = 'id'

    def list(self, request, *args, **kwargs):
        if isinstance(request.resolver_match.kwargs.get('id', None), int):
            return super().retrieve(request, *args, **kwargs)
        return super().list(request)

    def create(self, request, *args, **kwargs):
        title = request.data.get('title')
        if title is None:
            raise ValidationError({'title': 'Must not be empty'})
        return super().create(request, *args, **kwargs)

    def update(self, request, *args, **kwargs):
        response = super().update(request, *args, **kwargs)
        if response.status_code == 200:
            department = response.data
            department_id = department['id']
            cache.set(f'department_data_{department_id}', {
                'title': department['title'],
                'slug': department['slug'],
            })
        return response

    def delete(self, request, *args, **kwargs):
        department_id = request.data.get('id')
        response = super().delete(request, *args, **kwargs)
        if response.status_code == 204:
            cache.delete(f'department_data_{department_id}')
        return response

Это urlpatterns:

urlpatterns = [
    path('get/departments', DepartmentView.as_view()),
    path('api/new', DepartmentView().as_view()),
    path('api/update', DepartmentView().as_view()),
    path('api/<int:id>', DepartmentView.as_view()),
    path('api/empl', EmployeeView.as_view()),

    path('admin/', admin.site.urls),
]

Возможно, мне следовало использовать ViewSets, но не в этом дело. Кроме того, это работало. Но я хотел написать web-сервис и veb-приложение. Дело уперлось в то, что я не смог написать что-то похожее на вышеописанное с помощью Class-Based Views в Django. Вот мой View:

from django.http import HttpResponseRedirect, HttpResponse, HttpRequest
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy, reverse
from django.views import View
from django.views.decorators.http import require_http_methods
from django.views.generic import ListView, CreateView, FormView, DetailView, RedirectView, TemplateView
from department.models.models import Department, Employee
from department.forms.forms import DeptForm
from django.views.generic.edit import DeletionMixin, DeleteView

class DepartmentsCustomView(ListView, DetailView, DeleteView, CreateView):
    object_list = Department.objects.all().order_by('title')
    model = Department
    allow_empty = False
    form_class = DeptForm
    initial = {}
    success_url = 'main_page'
    object = None

    def get(self, request, *args, **kwargs):
                context = super().get_context_data(**kwargs)
        context['employees'] = Employee.objects.filter(department__id=
                                                       request.resolver_match.kwargs.get('pk'))
        return render(request, super().get_template_names(), context)

    def delete(self, request, *args, **kwargs):
        super().delete(request, *args, **kwargs)
        return HttpResponseRedirect(reverse('main_page'))

    def post(self, request, *args, **kwargs):
        if request.method == 'POST':
            form = DeptForm(request.POST)
            if form.is_valid():
                dept = form.save(commit=True)
                dept.save()
                context = super().get_context_data()
                return render(request, 'main_page.html', context)
        return render(request, 'add_new_dept.html', {'form': form})

    def put(self, request, *args, **kwargs):
        self.post(request, *args, **kwargs)

Вот как стали выглядеть urlpatterns:

urlpatterns = [
    path('get/departments', DepartmentView.as_view()),
    path('api/new', DepartmentView().as_view()),
    path('api/update', DepartmentView().as_view()),
    path('api/<int:id>', DepartmentView.as_view()),
    path('api/empl', EmployeeView.as_view()),

    path('admin/', admin.site.urls),

    path('', DepartmentsCustomView.as_view(template_name='main_page.html'), name='main_page'),
    path('<int:pk>', DepartmentsCustomView.as_view(template_name='department_detail.html'), name='department_detail'),
    path('<int:pk>/delete', DepartmentsCustomView.as_view(template_name='dept_deletion.html'), name='dept_deletion'),
    path('post', DepartmentsCustomView.as_view(template_name='add_new_dept.html'), name='add_new_dept'),
    path('<int:pk>/update', DepartmentsCustomView.as_view(template_name='add_new_dept.html'), name='add_new_dept'),
]

Но когда я пытаюсь удалить отдел, отдел удаляется из базы данных, но я остаюсь на странице 'localhost//25/delete' Я получаю эту ошибку:

Ошибка значения в /25/delete

Представление department.views.views.DepartmentsCustomView не вернуло объект HttpResponse. Вместо него возвращается None. Когда я пытаюсь добавить новый отдел, он перенаправляет меня на форму, и отдел создается в базе данных, но я остаюсь на странице 'localhost/post'. То есть я не перенаправляюсь на succses_url, а DepartmentsCustomView работает отдельными частями, и то не полностью. Возможно потому, что я переписал метод get и определил template_name в urlpatterns . Возможно, это можно исправить с помощью Mixin, но я не знаю как. Я прочитал много информации, django.views.generic исходный код, вопросы на stackoverflow, включая этот вопрос Django - Calling one class method from another in Class Based View. Я перепробовал все свои идеи и буду благодарен за любую подсказку, которая поможет мне закончить начатое. Спасибо, что дочитали до конца.

Вернуться на верх