views:

129

answers:

2

Hi,

I'd like to set up a filter in my app...I'd like to have my filters being done in increments, kinda like what is running at this site. So far my filter views are separate (is there a way of combining the filtering logic into one view?) and I'm supposing I'll need some way of saving the chosen filter (possibly sessions...but I'm not sure how to do this). My code is as below:

def year_filter(request, year):   
vehicle_query = Vehicle.objects.filter(common_vehicle__year__year__exact=year).exclude(status__status='Incoming')
vehicle_list = vehicle_query.order_by('common_vehicle__series__model__manufacturer__manufacturer', 'common_vehicle__series__model__model', 'common_vehicle__year')

vehicle = paginate(request, vehicle_list)

year_count = vehicle_query.order_by('-common_vehicle__year__year').values('common_vehicle__year__year').annotate(count=Count('id'))
make_count = vehicle_query.order_by('common_vehicle__series__model__manufacturer__manufacturer').values('common_vehicle__series__model__manufacturer__manufacturer').annotate(count=Count('id'))
style_count = vehicle_query.order_by('common_vehicle__body_style__style').values('common_vehicle__body_style__style').annotate(count=Count('id'))
color_count = vehicle_query.order_by('exterior_colour__exterior_colour').values('exterior_colour__exterior_colour').annotate(count=Count('id'))

return render_to_response('vehicles.html', {'vehicle': vehicle, 'make_count': make_count, 'year_count': year_count, 'style_count': style_count, 'color_count': color_count,})

def make_filter(request, make):       
vehicle_query = Vehicle.objects.filter(common_vehicle__series__model__manufacturer__manufacturer=make).exclude(status__status='Incoming')
vehicle_list = vehicle_query.order_by('common_vehicle__series__model__manufacturer__manufacturer', 'common_vehicle__series__model__model', 'common_vehicle__year')

vehicle = paginate(request, vehicle_list)

year_count = vehicle_query.order_by('-common_vehicle__year__year').values('common_vehicle__year__year').annotate(count=Count('id'))
make_count = vehicle_query.order_by('common_vehicle__series__model__manufacturer__manufacturer').values('common_vehicle__series__model__manufacturer__manufacturer').annotate(count=Count('id'))
series_count = vehicle_query.order_by('common_vehicle__series__series').values('common_vehicle__series__series').annotate(count=Count('id'))
style_count = vehicle_query.order_by('common_vehicle__body_style__style').values('common_vehicle__body_style__style').annotate(count=Count('id'))
color_count = vehicle_query.order_by('exterior_colour__exterior_colour').values('exterior_colour__exterior_colour').annotate(count=Count('id'))

return render_to_response('vehicles.html', {'vehicle': vehicle, 'make_count': make_count, 'series_count': series_count, 'year_count': year_count, 'style_count': style_count, 'color_count': color_count,})

def series_filter(request, model):
vehicle_query = Vehicle.objects.filter(common_vehicle__series__series=model).exclude(status__status='Incoming')
vehicle_list = vehicle_query.order_by('common_vehicle__series__series', 'common_vehicle__series__model__model', 'common_vehicle__year')

vehicle = paginate(request, vehicle_list)

year_count = vehicle_query.order_by('-common_vehicle__year__year').values('common_vehicle__year__year').annotate(count=Count('id'))
make_count = vehicle_query.order_by('common_vehicle__series__model__manufacturer__manufacturer').values('common_vehicle__series__model__manufacturer__manufacturer').annotate(count=Count('id'))
style_count = vehicle_query.order_by('common_vehicle__body_style__style').values('common_vehicle__body_style__style').annotate(count=Count('id'))
color_count = vehicle_query.order_by('exterior_colour__exterior_colour').values('exterior_colour__exterior_colour').annotate(count=Count('id'))

return render_to_response('vehicles.html', {'vehicle': vehicle, 'make_count': make_count, 'year_count': year_count, 'style_count': style_count, 'color_count': color_count,})

def body_filter(request, body):
vehicle_query = Vehicle.objects.filter(common_vehicle__body_style__style=body).exclude(status__status='Incoming')
vehicle_list = vehicle_query.order_by('common_vehicle__series__model__manufacturer__manufacturer', 'common_vehicle__series__model__model', 'common_vehicle__year')

vehicle = paginate(request, vehicle_list)

year_count = vehicle_query.order_by('-common_vehicle__year__year').values('common_vehicle__year__year').annotate(count=Count('id'))
make_count = vehicle_query.order_by('common_vehicle__series__model__manufacturer__manufacturer').values('common_vehicle__series__model__manufacturer__manufacturer').annotate(count=Count('id'))
style_count = vehicle_query.order_by('common_vehicle__body_style__style').values('common_vehicle__body_style__style').annotate(count=Count('id'))
color_count = vehicle_query.order_by('exterior_colour__exterior_colour').values('exterior_colour__exterior_colour').annotate(count=Count('id'))

return render_to_response('vehicles.html', {'vehicle': vehicle, 'make_count': make_count, 'year_count': year_count, 'style_count': style_count, 'color_count': color_count,})

def color_filter(request, color):
vehicle_query = Vehicle.objects.filter(exterior_colour__exterior_colour=color).exclude(status__status='Incoming')
vehicle_list = vehicle_query.order_by('common_vehicle__series__model__manufacturer__manufacturer', 'common_vehicle__series__model__model', 'common_vehicle__year')

vehicle = paginate(request, vehicle_list)

year_count = vehicle_query.order_by('-common_vehicle__year__year').values('common_vehicle__year__year').annotate(count=Count('id'))
make_count = vehicle_query.order_by('common_vehicle__series__model__manufacturer__manufacturer').values('common_vehicle__series__model__manufacturer__manufacturer').annotate(count=Count('id'))
style_count = vehicle_query.order_by('common_vehicle__body_style__style').values('common_vehicle__body_style__style').annotate(count=Count('id'))
color_count = vehicle_query.order_by('exterior_colour__exterior_colour').values('exterior_colour__exterior_colour').annotate(count=Count('id'))

return render_to_response('vehicles.html', {'vehicle': vehicle, 'make_count': make_count, 'year_count': year_count, 'style_count': style_count, 'color_count': color_count,})
+1  A: 

This sort of logic is what managers are for. Even if you decide not to use managers, you should be factoring out common code in some other way that you're familiar with. (Prefer procedural programming? Write a utility function. Familiar with OOP? Create callable class-based views which inherit from a class that contains the filtering logic.) If you find yourself copying and pasting code like this, it's a sign that you're going to run into trouble before too long.

ozan
so how exactly do I go about solving my problem? I'm not so good at Django...this is my first app BTW
Stephen
A: 

You write a manager. From your example it needs at least one method for vehicle_query, one method for .annotate(count=Count('id')) and maybe some for the repeated order_by()s.

If you need the methods to nest, so that you can do vehicle_query(year).with_counts() as well as with_counts().vehicle_query(year), you need to make your own QuerySet too, that is: inherit from QuerySet, add the methods there, then use that queryset in your manager, and map methods in the manager to the methods in the queryset.

from django.db import models
from django.db.models.query import QuerySet

class VehicleQuerySet(QuerySet):
    def vehicle_query(self, year):
        return self.filter(common_vehicle__year__year__exact=year).exclude(status__status='Incoming')

class VehicleManager(models.Manager):
    def get_query_set(self):
        return VehicleQuerySet(self.model)

    def vehicle_query(self, year):
        return self.get_query_set().vehicle_query(year)

class WhateverModel(models.Model):
    ...
    objects = models.Manager() # keeping the default manager
    smart_objects = VehicleManager() # additional manager

Then in your views:

vehicle_query = Vehicle.smart_objects.vehicle_query(year)
kaleissin
Is there another way of doing this...perhaps using sessions? Maybe it's just me but I can't begin to understand this bit of code
Stephen
This is a very common way. follow ozan link to learn about managers.
vikingosegundo
BTW, will this preserve my values in between queries?
Stephen
Just wondering...is there a way to pass all the values i.e. year, make, series, colour and body style as one function such as vehicle_query?
Stephen
47, certainly. Either you'll have to return year_count, make_count etc. from a single method, or you'd need a method for each. Have you done the python tutorial? See that for how to return more than one thing at a time in a function/method.
kaleissin