我刚刚为两个不同的模型写了两个视图函数,但它们非常相似,只是在一些名称上有所不同。合并这两个视图函数以防止代码重复的最佳方法是什么?
这些是视图函数:
def manager_scientific(request, *args, **kwargs):
context = {}
if request.user.role == 'manager':
template = loader.get_template('reg/scientific-manager-dashboard.html')
users = User.objects.filter(role='applicant', isPreRegistered=True, scientificinfo__is_interviewed=True).order_by('-date_joined')
approved = ScientificInfo.objects.filter(is_approved__exact='0').all()
context['users'] = users
context['all_users'] = len(users)
context['approved'] = len(approved)
context['survey_choices'] = SURVEY_CHOICES
if request.GET.get('user', 'all') == 'all':
users = users
if request.GET.get('user', 'all') == 'new':
users = users.filter(scientificinfo__is_approved__exact='0')
field_list = request.GET.getlist('field')
if field_list:
if 'None' in field_list:
users = users.filter(fields__title=None) | users.filter(fields__title__in=field_list)
else:
users = users.filter(fields__title__in=field_list)
gender_list = request.GET.getlist('gender')
if gender_list:
users = users.filter(gender__in=gender_list)
education_list = request.GET.getlist('education')
if education_list:
users = users.filter(educationalinfo__grade__in=education_list)
work_list = request.GET.getlist('work')
if work_list:
users = users.filter(workinfo__position__in=work_list)
province_list = request.GET.getlist('province')
if province_list:
if 'None' in province_list:
users = users.filter(prevaddress__address_province__in=province_list) | users.filter(
prevaddress__address_province=None)
else:
users = users.filter(prevaddress__address_province__in=province_list)
query_string = request.GET.get('query_string')
if query_string:
name_query = None
for term in query_string.split():
if name_query:
name_query = name_query & (Q(first_name__contains=term) | Q(last_name__contains=term))
else:
name_query = Q(first_name__contains=term) | Q(last_name__contains=term)
users = users.filter(name_query |
Q(educationalinfo__field__contains=query_string) |
Q(educationalinfo__tendency__contains=query_string) |
Q(educationalinfo__university_name__contains=query_string) |
Q(workinfo__organization__contains=query_string) |
Q(ngoinfo__ngo_name__contains=query_string) |
Q(melli_code__contains=query_string))
users = users.distinct()
context['grade_choices'] = []
for g, grade in EDUCATIONAL_GRADE_CHOICES:
count = EducationalInfo.objects.filter(user__in=users, grade=g).count()
context['grade_choices'].append((g, grade, count))
context['work_position_choices'] = []
for p, position in WORK_POSITION_CHOICES:
count = WorkInfo.objects.filter(user__in=users, position=p).count()
context['work_position_choices'].append((p, position, count))
provinces = users.values_list('prevaddress__address_province')
provinces = Counter([d[0] for d in provinces])
context['provinces'] = provinces.items()
paginator = Paginator(users, 25) # Show 25 contacts per page.
page_number = request.GET.get('page', 1)
page_obj = paginator.get_page(page_number)
context['users'] = page_obj
context['is_interviewed'] = ScientificInfo.objects.filter(is_approved__exact='0', user__is_staff=False).count()
context['not_interviewed'] = ScientificInfo.objects.filter(is_interviewed=True, user__is_staff=False).count()
context['men'] = users.filter(gender="male").count()
context['women'] = users.filter(gender="female").count()
context['query_string'] = query_string
return HttpResponse(template.render(request=request, context=context))
和另一个:
def manager_religious(request, *args, **kwargs):
context = {}
if request.user.role == 'manager':
template = loader.get_template('reg/religious-manager-dashboard.html')
users = User.objects.filter(role='applicant', isPreRegistered=True, religiousinfo__is_interviewed=True).order_by('-date_joined')
approved = ReligiousInfo.objects.filter(is_approved__exact='0').all()
context['users'] = users
context['all_users'] = len(users)
context['approved'] = len(approved)
context['survey_choices'] = SURVEY_CHOICES
if request.GET.get('user', 'all') == 'all':
users = users
if request.GET.get('user', 'all') == 'new':
users = users.filter(religiousinfo__is_approved__exact='0')
field_list = request.GET.getlist('field')
if field_list:
if 'None' in field_list:
users = users.filter(fields__title=None) | users.filter(fields__title__in=field_list)
else:
users = users.filter(fields__title__in=field_list)
gender_list = request.GET.getlist('gender')
if gender_list:
users = users.filter(gender__in=gender_list)
education_list = request.GET.getlist('education')
if education_list:
users = users.filter(educationalinfo__grade__in=education_list)
work_list = request.GET.getlist('work')
if work_list:
users = users.filter(workinfo__position__in=work_list)
province_list = request.GET.getlist('province')
if province_list:
if 'None' in province_list:
users = users.filter(prevaddress__address_province__in=province_list) | users.filter(
prevaddress__address_province=None)
else:
users = users.filter(prevaddress__address_province__in=province_list)
query_string = request.GET.get('query_string')
if query_string:
name_query = None
for term in query_string.split():
if name_query:
name_query = name_query & (Q(first_name__contains=term) | Q(last_name__contains=term))
else:
name_query = Q(first_name__contains=term) | Q(last_name__contains=term)
users = users.filter(name_query |
Q(educationalinfo__field__contains=query_string) |
Q(educationalinfo__tendency__contains=query_string) |
Q(educationalinfo__university_name__contains=query_string) |
Q(workinfo__organization__contains=query_string) |
Q(ngoinfo__ngo_name__contains=query_string) |
Q(melli_code__contains=query_string))
users = users.distinct()
context['grade_choices'] = []
for g, grade in EDUCATIONAL_GRADE_CHOICES:
count = EducationalInfo.objects.filter(user__in=users, grade=g).count()
context['grade_choices'].append((g, grade, count))
context['work_position_choices'] = []
for p, position in WORK_POSITION_CHOICES:
count = WorkInfo.objects.filter(user__in=users, position=p).count()
context['work_position_choices'].append((p, position, count))
provinces = users.values_list('prevaddress__address_province')
provinces = Counter([d[0] for d in provinces])
context['provinces'] = provinces.items()
paginator = Paginator(users, 25) # Show 25 contacts per page.
page_number = request.GET.get('page', 1)
page_obj = paginator.get_page(page_number)
context['users'] = page_obj
context['is_interviewed'] = ReligiousInfo.objects.filter(is_approved__exact='0', user__is_staff=False).count()
context['not_interviewed'] = ReligiousInfo.objects.filter(is_interviewed=True, user__is_staff=False).count()
context['men'] = users.filter(gender="male").count()
context['women'] = users.filter(gender="female").count()
context['query_string'] = query_string
return HttpResponse(template.render(request=request, context=context))
唯一的区别是模型名和模板地址。以及我如何将它们重写为基于类的格式?
您可以创建一个从View class继承的公共类,然后创建两个从前一个继承的独立类。如
class ManagerView(View)
template_name = None
model = None
def get(self, request):
...
template = loader.get_template(self.template_name)
approved = self.model.objects.filter(is_approved__exact='0').all()
...
class ManagerReligiousView(ManagerView)
template_name = 'reg/religious-manager-dashboard.html'
model = ReligiousInfo
class ManagerScientificView(ManagerView)
template_name ='reg/scientific-manager-dashboard.html'
model = ScientificInfo
基于类的视图的另一种方法是利用很少使用的能力,在url中传递配置选项。
class SomeView( AnyClassBasedView):
foo = 'bar'
在urls . py
path( '/do_bar/<int:pk>', SomeView.as_view(), name='do_bar'),
path( '/do_baz/<int:pk>', SomeView.as_view( foo='baz'), name='do_baz'),
在SomeView中,self.foo
的条件测试。注意,在urls.py
中使用任何此类参数之前,必须在类定义中声明具有默认值的参数。
一种变体是使用write视图来处理>1方法通过查询self.kwargs
来访问对象
path( '/x/<int:pk>', X_View.as_view(), name='x_by_pk'),
path( '/x/<str:order_number>', X_View.as_view(), name='x_by_order'),
其中get_object
方法通常被子类化:
class X_View( DetailView):
...
def get_object( self, queryset=None):
if 'pk' in self.kwargs:
obj = get_object_or_404( X, pk=self.kwargs['pk'] )
elif 'order_number' in self.kwargs:
obj = get_object_or_404( X, order_number=self.kwargs['order_number'] )
...
else:
raise ConfigurationError( 'Check urls.py. No valid kwarg was parsed')
return obj
注意,这是一个简化的get_object
,忽略了queryset
。请参阅get_object
的代码,以获得将此模式插入的更好的模板。经典的cbv来拯救。