Как мне применить Mixins ко всем CBV в приложении django?

#python #django

#python #django

Вопрос:

Допустим, я хочу использовать LoginRequiredMixin и UserPermissionMixin, созданные мной, и применить их ко всем представлениям в приложении. Это всего лишь пример, у меня также могут быть mixins, которые добавляют некоторый контекст или делают другие вещи.

Я мог бы сделать это вручную, например, в этом представлении:

 class MyCreateView(LoginRequiredMixin, UserPermissionMixin, CreateView)
 

Но, поскольку у меня много просмотров, и у меня могут быть другие конкретные mixins для некоторых представлений, это становится беспорядочным и сложным в управлении.

Одним из решений, которое пришло на ум, было бы создание новых классов для общих представлений:

 class DecoratedCreateView(LoginRequiredMixin, UserPermissionMixin, CreateView):
    pass


class DecoratedDetailView(LoginRequiredMixin, UserPermissionMixin, DetailView):
    pass


class DecoratedUpdateView(LoginRequiredMixin, UserPermissionMixin, UpdateView):
    pass


class DecoratedDeleteView(LoginRequiredMixin, UserPermissionMixin, DeleteView):
    pass
 

а затем используйте их в качестве моих общих представлений:

 class MyCreateView(DecoratedCreateView)
 

Это хороший подход? Должен ли я добавлять какие-либо методы в классы выше или я просто оставляю их пустыми, и все будет работать, как ожидалось?
Есть ли какой-либо другой способ добиться этого, возможно, в urls.py ?

Ответ №1:

Ваш подход хорош. Я делал это для некоторых проектов с небольшой разницей:

myapp/views/generic.py

 from django.views.generic import (
    CreateView as BaseCreateView,
    DetailView as BaseDetailView,
    UpdateView as BaseUpdateView,
    DeleteView as BaseDeleteView,
)

__all__ = ['MyappMixin', 'CreateView', 'DetailView', 'UpdateView', 'DeleteView']


class MyappMixin(LoginRequiredMixin, UserpermissionMixin):
    pass


class CreateView(MyappMixin, BaseCreateView):
    pass


class DetailView(MyappMixin, BaseDetailView):
    pass


class UpdateView(MyappMixin, BaseUpdateView):
    pass


class DeleteView(MyappMixin, BaseDeleteView):
    pass
 

myapp/views/base.py

 from .generic import CreateView

class MyCreateView(CreateView):
    pass
 

Он работает нормально, без особых проблем и позволяет вам легко пропустить mixin в исключительных случаях, если это необходимо.

Согласно usecase, другим решением может быть использование промежуточных программ или контекстных процессоров.

 class MyMiddleware:

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        is_in_myapp = request.resolver_match.app_name == 'myapp'
        if is_in_myapp and not request.user.is_authenticated:
            response = HttpResponse("Permission denied", status=403)
        else:
            response = self.get_response(request)
        return response
 

Комментарии:

1. Спасибо, я думаю, эта идея сэкономила мне 2 часа ручного редактирования всех существующих обновлений и CreateViews вместо изменения импорта!