是否有更干的方法来创建这些重复的基于 django class 的视图和 URL 模式?

Is there a more DRY way to create these repetitive django class based views, and URL patterns?

有没有更好、更干的方法来在 Django 中创建重复的视图和 URL 集?以下是我的观点和网址。正如您可能看到的那样,目前有两组视图和 url 如果不是不同的模型名称,它们将是相同的。有没有办法一次创建 3 个 classes 作为 mixin 或类似的东西,这样我添加一组新的 classes 所要做的就是将模型名称传递给一个函数或 child class?我可以为网址做类似的事情吗?我在这里发现了一个相关问题 Class Based Generic Views and DRY,但不确定该问题的答案是否以及如何适用于此处或是否相关。

视图中的相关部分:

class AlertMessageUpdate(LoginRequiredMixin, UpdateView):
    template_name = "LibreBadge/applicationadmin/AlertMessage/alertMessageForm.html"
    model = AlertMessage
    fields = "__all__"

class AlertMessageCreate(LoginRequiredMixin, CreateView):
    template_name = "LibreBadge/applicationadmin/AlertMessage/alertMessageForm.html"
    model = AlertMessage
    fields = "__all__"

class AlertMessageList(LoginRequiredMixin, ListView):
    template_name = "LibreBadge/applicationadmin/AlertMessage/alertMessageList.html"
    model = AlertMessage

class BadgeTemplateUpdate(LoginRequiredMixin, UpdateView):
    template_name = "LibreBadge/applicationadmin/BadgeTemplate/badgeTemplateForm.html"
    model = BadgeTemplate
    fields = "__all__"

class BadgeTemplateCreate(LoginRequiredMixin, CreateView):
    template_name = "LibreBadge/applicationadmin/BadgeTemplate/badgeTemplateList.html"
    model = BadgeTemplate

class BadgeTemplateList(LoginRequiredMixin, ListView):
    template_name = "LibreBadge/applicationadmin/BadgeTemplate/badgeTemplateList.html"
    model = BadgeTemplate

urls.py中的相关部分:

    url(r'^applicationadmin/alertmessages/update/(?P<pk>[-\w]+)/$', views.AlertMessageUpdate.as_view(), name='AlertMessageUpdate'),
    url(r'^applicationadmin/alertmessages/create/$', views.AlertMessageCreate.as_view(), name='AlertMessageCreate'),
    url('applicationadmin/alertmessages/$', views.AlertMessageList.as_view(), name='AlertMessageList'),
    url(r'^applicationadmin/badgetemplates/update/(?P<pk>[-\w]+)/$', views.BadgeTemplateUpdate.as_view(), name='BadgeTemplateUpdate'),
    url(r'^applicationadmin/badgetemplates/create/$', views.BadgeTemplateCreate.as_view(), name='BadgeTemplateCreate'),
    url('applicationadmin/badgetemplates/$', views.BadgeTemplateList.as_view(), name='BadgeTemplateList'),

此问题的答案将在 LibreBadge, LibreBadge GitHub 中使用,这是一个开源、MIT 许可的 ID 徽章解决方案。如果这是您的风格,请随时以拉取请求的形式回答这个问题!

我找到了解决重复视图问题的方法!

def applicationAdminCRUDFunction(model, modelName, fields):
    def templateNameGenerator(suffix):
        return("LibreBadge/applicationadmin/" + modelName + "/" + modelName + suffix + ".html")
    viewsDictionary = {}
    viewsDictionary['CreateView'] = type(modelName + 'CreateView', (CreateView,), {'template_name': templateNameGenerator('Form'),'model': model, 'fields': fields})
    viewsDictionary['ListView'] = type(modelName + 'ListView', (ListView,), {'template_name': templateNameGenerator('List'),'model': model})
    viewsDictionary['UpdateView'] = type(modelName + 'UpdateView', (UpdateView,), {'template_name': templateNameGenerator('Form'),'model': model, 'fields': fields})
    viewsDictionary['DeleteView'] = type(modelName + 'DeleteView', (CreateView,), {'success_url': reverse_lazy(modelName + 'Create'),'model': model})
    return(viewsDictionary)

AlertMessageViews = applicationAdminCRUDFunction(AlertMessage, 'AlertMessage', '__all__')
BadgeTemplateViews = applicationAdminCRUDFunction(BadgeTemplate, 'BadgeTemplate', '__all__')

我创建了一个函数,它使用类型动态创建基于 class 的视图(了解有关使用类型创建 classes here 的更多信息)并将它们分配给字典。

现在我只需调用 applicationAdminCRUDFunction 并将其值分配给一个变量。然后我可以像这样调用 urls.py 中的视图

    url(r'^alertmessages/update/(?P<pk>[-\w]+)/$', views.AlertMessageViews.get('UpdateView').as_view(), name='AlertMessageUpdate'),

为了解决重复的 URL 模式问题,我创建了一个函数 return 带有 modelName 参数

的 url 列表
def applicationAdminURLS(modelName):
    return[
        path(modelName + '/create', eval('views.' + modelName + 'Views' + ".get('CreateView').as_view()"), name= modelName + 'Create'),
        path('', eval('views.' + modelName + 'Views' + ".get('ListView').as_view()"), name= modelName + 'List'),
        path(modelName + '/update/(<int:pk>/', eval('views.' + modelName + 'Views' + ".get('UpdateView').as_view()"), name= modelName + 'Update'),
        ]

然后我通过使用 include 创建一个路径模式来调用该函数,并将 applicationAdminURLS 函数作为参数传递给 include

    path('alertmessages/', include(applicationAdminURLS('AlertMessage')), name='alertmessages'),
    path('badgetemplates/', include(applicationAdminURLS('BadgeTemplate')), name='badgetemplates'),