Skip to main content
 首页 » 编程设计

python之如何将 Mixins 应用于 django 应用程序中的所有 CBV

2024年09月03日26kerrycode

假设我想使用我自己创建的 LoginRequiredMixin 和 UserPermissionMixin,并将它们应用于应用程序中的所有 View 。这只是一个例子,我可能还有添加一些上下文或做其他事情的混合。

我可以手动完成,例如这个 View :

class MyCreateView(LoginRequiredMixin, UserPermissionMixin, CreateView) 

但是,由于我有很多 View ,而且我可能对某些 View 有其他特定的混合,这会变得困惑且难以管理。

想到的一个解决方案是为通用 View 创建新类:

class DecoratedCreateView(LoginRequiredMixin, UserPermissionMixin, CreateView): 
    pass 
 
 
class DecoratedDetailView(LoginRequiredMixin, UserPermissionMixin, DetailView): 
    pass 
 
 
class DecoratedUpdateView(LoginRequiredMixin, UserPermissionMixin, UpdateView): 
    pass 
 
 
class DecoratedDeleteView(LoginRequiredMixin, UserPermissionMixin, DeleteView): 
    pass 

然后,将这些用作我的通用 View :

class MyCreateView(DecoratedCreateView) 

这是一个好方法吗?我是否必须在上面的类中添加任何方法,或者我只是将它们留空并且它会按预期工作? 有没有其他方法可以实现这一点,也许在 urls.py 中?

请您参考如下方法:

你的方法很好。我一直在为一些略有不同的项目这样做:

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。

根据用例,另一种解决方案可能是使用 middlewares或 context processors .

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