如何将两个逻辑与模板有差异的Django TemplateView合并为单个视图以符合DRY原则
实现方案
两个视图的核心差异仅为模板路径、不同状态下的过滤条件,我们可以通过提取公共逻辑的方式遵循DRY原则,以下是两种常用实现方案:
方案1:抽象公共基类(推荐,扩展性更强)
将通用逻辑封装到父类,子类仅声明差异化配置:
# 公共基类,所有通用逻辑仅实现一次 class BaseProgressView(LoginRequiredMixin, TemplateView): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['progress'] = self.kwargs.get('progress', 'in_progress') # 调用子类实现的方法获取对应场景的过滤条件 filters = self.get_filters(context['progress']) context['objects'] = Model.objects.filter(**filters) return context def get_filters(self, progress): if progress == 'in_progress': base_filters = {'progress': 'in_progress'} extra_filters = self.get_in_progress_extra_filters() else: base_filters = {'progress__iexact': progress} extra_filters = self.get_other_progress_extra_filters() return {**base_filters, **extra_filters} # 子类按需重写以下两个方法返回额外过滤条件 def get_in_progress_extra_filters(self): return {} def get_other_progress_extra_filters(self): return {} # 原View1仅需写差异化逻辑 class View1(BaseProgressView): template_name = 'temp1.html' def get_other_progress_extra_filters(self): return {'accepted': self.request.user} # 原View2仅需写差异化逻辑 class View2(BaseProgressView): template_name = 'temp2.html' def get_in_progress_extra_filters(self): return {'created': self.request.user} def get_other_progress_extra_filters(self): return {'created_by': self.request.user}
方案2:单视图+URL注入配置(更简洁,适合无后续扩展需求的场景)
如果不需要保留多个视图类,可以直接通过as_view()传递差异化参数,仅用单个视图实现:
首先修改urls.py,在注册路由时注入配置:
# urls.py urlpatterns = [ # 原View1的路由,注入对应配置 path('view1/<str:progress>/', MergedProgressView.as_view( template_name='temp1.html', filter_config={ 'in_progress_user_field': None, 'other_user_field': 'accepted' } ), name='view1'), # 原View2的路由,注入对应配置 path('view2/<str:progress>/', MergedProgressView.as_view( template_name='temp2.html', filter_config={ 'in_progress_user_field': 'created', 'other_user_field': 'created_by' } ), name='view2'), ]
然后实现合并后的视图:
# views.py class MergedProgressView(LoginRequiredMixin, TemplateView): # 由as_view方法注入配置,不需要修改核心逻辑 filter_config = None def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['progress'] = self.kwargs.get('progress', 'in_progress') filters = {} if context['progress'] == 'in_progress': filters['progress'] = 'in_progress' user_field = self.filter_config['in_progress_user_field'] else: filters['progress__iexact'] = context['progress'] user_field = self.filter_config['other_user_field'] # 配置了用户关联字段就添加过滤条件 if user_field: filters[user_field] = self.request.user context['objects'] = Model.objects.filter(**filters) return context
内容的提问来源于stack exchange,提问作者乂TØXIC乂
相关产品推荐
相关产品推荐

