Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically filter ListView CBV in Django 1.7

I've read the official documentation on dynamically filtering ListView, but am still confused about how to actually use it.

I currently have a simple model, let's call it Scholarship:

class Scholarship(models.Model):
    title = models.CharField(max_length=255)
    submitted_date = models.DateField(auto_now=True, verbose_name='Date Submitted')
    EXPERIENCE_LEVEL_CHOICES = (
        ('A', 'Any'),
        ('S', 'Student'),
        ('G', 'Graduate')
    )
    experience_level = models.CharField(max_length=1, choices=EXPERIENCE_LEVEL_CHOICES, default='A')

I have a page where I'm showing all of these scholarships, using ListView:

views.py

from django.views.generic import ListView
from .models import Scholarship


class ScholarshipDirectoryView(ListView):
    model = Scholarship
    template_name = 'scholarship-directory.html'

urls.py

from django.conf.urls import patterns, url

from .views import ScholarshipDirectoryView

urlpatterns = patterns('',
    url(r'^$', ScholarshipDirectoryView.as_view(), name='scholarship_directory'),
)

I'm trying to generate links on the home page of the site that will return filtered versions of this ListView. For example, if someone clicks on a "show scholarships for graduate students" link, only scholarships with experience_level='G' will be shown.

I have no problem returning this queryset via the shell -> Scholarship.objects.filter(experience_level__exact='G')

I'm just unsure about how to dynamically filter the ListView via a dropdown or URL. Not looking to use a plugin, but rather understand how dynamically querying/filtering works in Django.

like image 858
rnevius Avatar asked Sep 04 '14 09:09

rnevius


1 Answers

First of all you need to change your urls.py so that it'll pass the experience as a parameter. Something like this:

urlpatterns = patterns('',
    url(r'^(?P<exp>[ASG])$', ScholarshipDirectoryView.as_view(), name='scholarship_directory'),
)

(the above will return 404 if /A or /S or /G is not passed)

Now, in kwargs attribute of the CBV we will have a kwarg named exp which can be used by the get_queryset method to filter by experience level.

class ScholarshipDirectoryView(ListView):
    model = Scholarship
    template_name = 'scholarship-directory.html'

    def get_queryset(self):
        qs = super(ScholarshipDirectoryView, self).get_queryset()
        return qs.filter(experience_level__exact=self.kwargs['exp'])
like image 129
Serafeim Avatar answered Oct 08 '22 03:10

Serafeim