Django-filter i "Generic View"


17 lipca 2013


Przykład użycia Django-filter w widokach generycznych opartych na klasach

Django-filter to aplikacja, która umożliwia filtrowanie w ramach "QuerySet" frameworka. Biblioteka pozwala na wygenerowanie formularza w oparciu o model a następnie filtruje dane w zależności od wartości wybranych przez użytkownika. Django-filter jest przydatna gdy szybko musimy stworzyć mechanizm filtrowania np. dla listy. Dokumentacja modułu bardzo skromnie opisuje użycie w przypadku gdy korzystamy z widoków generycznych opartych na klasach. Gdy nie chcemy korzystać z Django-filter możemy skorzystać z dynamicznego filtrowania dostępnego dla CBV (widokach opartych na klasach) -zobacz.

Pomijam opis instalacji Django-filter - dostępny jest w dokumentacji.
Dla przykładu mamy następującą definicję modelu

class Clubs(models.Model):
    '''
    Clubs model 
    '''
    name=models.CharField(max_length=255, unique=True, verbose_name=_("Name"))
    city = models.ForeignKey(Cities, verbose_name =  _("City"))
    ...

Definicja widoku generycznego dla modelu może wyglądać następująco (pomijam importy modeli i dekoratorów):

class ClubsListView(ListView):
    """
    Club list
    """
    model = Clubs   
    template_name = 'clubs/list.html'
    paginate_by = 10
    
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return ListView.dispatch(self, request, *args, **kwargs)

 

Dodamy teraz filtrowanie w oparciu o Django-filter. Na początku musimy zaimportować moduł:

import django_filters    

Tworzymy klasę odpowiedzialną za filtrowanie:

class ClubsFilter(django_filters.FilterSet):
    '''
    Clubs dynamic filtering (django-filter)
    '''
    class Meta:
        model = Clubs
        fields = ['name', 'email']

W klasie "ClubsListView" nadpisujemy dwie metody związanymi z CBV:

class ClubsListView(ListView):
    ...
    
    def get_queryset(self):
        '''
        Modify QuerySet
        '''
        try:
            self.filter = ClubsFilter(self.request.GET, 
                                      queryset=Clubs.objects.all())
            return self.filter
        except:
            return Clubs.objects.all()
    
    
    def get_context_data(self, **kwargs):
        '''
        Return context
        '''
        context = super(ClubsListView, self).get_context_data(**kwargs)
                
        context['filter_form'] = self.filter.form.as_table
                        
        return context

W metodzie "get_queryset" zmieniamy domyślny "QuerySet" dla listy klubów (wykorzystujemy stworzoną klasę filtrowania  "ClubsListView"). W metodzie "get_context_data" zmieniamy "kontekst" dodając formularz filtrowania. 
Pozostaje nam umieścić formularz filtrowania w szablonie:

<form action="" method="get" class="filter-form">
<table>
        {{ filter_form }}
</table>
        <input type="submit" value="Szukaj" />
        <a class="reset-form" href="{% url list-clubs %}">Wyczyść filtr</a>
</form>

Musimy zmienić także wpis w urls.py dla listy klubów:

urlpatterns = patterns('',
    ...
    url(
        regex=r"^clubs/$",
        view=ClubsListView.as_view(),
        name="list-clubs"   
        ),                   
    url(
        regex=r"^clubs/(\w+)/$",
        view=ClubsListView.as_view(),
        name="list-clubs-filter"   
        ), 
    ...

Co zawiera blog?

Na blogu umieszczam wpisy dotyczące mojej pracy, zainteresowań. Głowna tematyka to programowanie oraz recenzje płyt oraz książek.

Wieczne Blue Lines


Artwork: Michael Nash, 3D-Del Naja
Ćwierćwiecze jednej z najważniejszych płyt ...

Kontrola nad schematem


South - po co i jak go używać?
Opis ...

Arkusze i xlwt


Przykład użycia biblioteki xlwt (scalanie, zwijanie wierszy, zamrażanie wierszy i ...

Odrobina relaksu


Fotografia - Tom Hingston
© EMI Records Ltd.
Recenzja albumu ...

Raport sportowy #8


Zdjęcie: Luke Stackpoole, Unsplash

Schematy finansowe


"Bogaty albo biedny. Po prostu różni mentalnie". Wrażenia.