Home > Mobile >  how to merge two views functions with minor differences
how to merge two views functions with minor differences

Time:07-15

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.

  • Related