I just wrote two view functions for two different models but they are very similar and only different in some names. what is the best way to merge these two view functions to prevent code repetition?
these are the view functions:
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))
and the other one:
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))
the only differences are in model names and template addresses. and also how can I rewrite them in a class based format?
CodePudding user response:
You can create one common class that inherits from View Class and then two separate classes that inherit from the previous one. e.g
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
CodePudding user response:
Another way with a class-based view is to emply the rarely-used ability to pass configuration options to it in the url.
class SomeView( AnyClassBasedView):
foo = 'bar'
In 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'),
And in SomeView, conditional tests on self.foo
. Note, you have to declare any such parameter with a default value in the class definition before you can use it in urls.py
.
A variant is to use write a view that can handle >1 method of accessing an object by interrogating 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'),
where typically the get_object
method is subclassed:
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
NB this is a simplified get_object
which ignores queryset
. See the code of get_object
for a better template to slot this pattern into. Classy CBVs to the rescue.