Deze tekst is het laatste deel van de Django klasse-gebaseerde weergave (CBV) onderzoekserie, waar we laten zien hoe we paging, zoekfunctie, en sorteren met behulp van ListView
kunnen implementeren - functies die vaak in de praktijk worden gebruikt. Als je de basisprincipes tot en met de vorige 7 delen hebt bekeken, zullen we dit keer samenvatten hoe we de gebruikelijke vereisten in webontwikkeling elegant kunnen afhandelen met CBV.
Voor de link naar het vorige deel, klik op de onderstaande link!
Klasse-gebaseerde weergave (CBV) Onderzoekserie ⑦ - Gebruik van Mixin en Toegangsbeheer
“Breid de Django ListView uit om krachtige lijstfunctionaliteiten te implementeren en verbeter de gebruikerservaring!”
1. ListView, meer mogelijkheden dan ooit
ListView
is een zeer handige Generic View voor het tonen van gegevenslijsten. Echter, in een echte webapplicatie zijn paging, zoekfunctie en sorteren essentiële functies om een grote hoeveelheid gegevens efficiënt te beheren.
In dit hoofdstuk bekijken we hoe we ListView
kunnen uitbreiden om deze praktische vereisten makkelijk en elegant met behulp van CBV te implementeren.
2. Paging toepassen
Het tonen van een grote hoeveelheid gegevens tegelijk is niet goed voor de gebruikerservaring. Paging vermindert de laadtijd voor gebruikers door gegevens op verschillende pagina's te verdelen, waardoor het gemakkelijker wordt om de gewenste informatie te vinden.
2.1 Basis Paging Instellingen
ListView
biedt ingebouwde paging functionaliteit. Je hoeft alleen maar de paginate_by
eigenschap in de viewklasse in te stellen.
Voorbeeld van views.py
from django.views.generic import ListView
from .models import Article
class ArticleListView(ListView):
model = Article
template_name = 'articles/article_list.html'
context_object_name = 'articles'
paginate_by = 10 # Toon 10 Article-objecten per pagina
paginate_by = 10
: Door deze instelling zalListView
automatisch de resultaten verdelen in pagina's van 10, en de paging-gerelateerde objecten (paginator
,page_obj
,is_paginated
) doorgeven aan de template context.
2.2 Paging UI in de Template Implementeren
In de template kun je de page_obj
gebruiken om schakelknoppen voor pagina's weer te geven, inclusief knoppen voor vorige/volgende pagina.
Voorbeeld van articles/article_list.html
<ul>
{% for article in articles %}
<li>{{ article.title }} - {{ article.created_at }}</li>
{% empty %}
<li>Er zijn nog geen artikelen gepubliceerd.</li>
{% endfor %}
</ul>
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1">« Einde</a>
<a href="?page={{ page_obj.previous_page_number }}">Vorige</a>
{% endif %}
<span class="current">
Pagina {{ page_obj.number }} / {{ paginator.num_pages }}
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">Volgende</a>
<a href="?page={{ paginator.num_pages }}">Laatste »</a>
{% endif %}
</span>
</div>
page_obj
: Dit object bevat de gegevens van de huidige pagina. Het biedt eigenschappen zoalshas_previous
,has_next
,previous_page_number
,next_page_number
, ennumber
.paginator
: Dit object bevat informatie over alle pagina's, zoals het totaal aantal pagina's vianum_pages
.
2.3 URL Verbinding Onderhouden
Bij het genereren van paging-links zie je dat de ?page=2
query parameter wordt gebruikt. ListView
herkent dit automatisch en toont de gegevens van de betreffende pagina.
3. Zoekfunctie Toevoegen
Het snel vinden van informatie op een website is zeer belangrijk. Laten we de zoekfunctie implementeren door ListView
uit te breiden.
3.1 Definiëren van het Formulier
Definieer eerst een eenvoudig formulier waarin de zoekterm kan worden ingevoerd.
Voorbeeld van forms.py
from django import forms
class ArticleSearchForm(forms.Form):
search_term = forms.CharField(label='Zoekterm', required=False)
3.2 ListView Aanpassen
We overschrijven de get_queryset()
methode van ListView
om de zoekfunctie te implementeren.
Voorbeeld van views.py
from django.views.generic import ListView
from django.db.models import Q
from .models import Article
from .forms import ArticleSearchForm
class ArticleListView(ListView):
model = Article
template_name = 'articles/article_list.html'
context_object_name = 'articles'
paginate_by = 10
def get_queryset(self):
queryset = super().get_queryset()
self.form = ArticleSearchForm(self.request.GET) # Formuliergegevens opgehaald uit GET-verzoek
if self.form.is_valid():
search_term = self.form.cleaned_data.get('search_term')
if search_term:
# Filter Articles met de zoekterm in de titel of inhoud
queryset = queryset.filter(
Q(title__icontains=search_term) | Q(content__icontains=search_term)
)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['search_form'] = self.form # Formulier naar de template doorgeven
return context
get_queryset()
: Dit is de methode die we overschrijven om de standaard queryset aan te passen.- Een formulier instantie wordt aangemaakt en, als de validatie slaagt, wordt de zoekterm uit de
cleaned_data
gehaald. Q-objecten
worden gebruikt omArticle
objecten te filteren waarin de zoekterm voorkomt in de titel (title
) of in de inhoud (content
) (__icontains
controleert de opneming zonder onderscheid in hoofdletters).get_context_data()
: Voegt het formulier aan de context toe zodat het in de template kan worden weergegeven.
3.3 Het Zoekformulier en Resultaten in de Template Weergeven
Voeg het zoekformulier toe aan de template en zorg ervoor dat de zoekresultaten behouden blijven tijdens het pagineren door de URL goed op te bouwen.
articles/article_list.html
<form method="get">
{{ search_form }}
<button type="submit">Zoeken</button>
</form>
<ul>
{% for article in articles %}
<li>{{ article.title }} - {{ article.created_at }}</li>
{% empty %}
<li>Geen zoekresultaten gevonden.</li>
{% endfor %}
</ul>
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1&search_term={{ search_form.search_term.value|default:'' }}">« Einde</a>
<a href="?page={{ page_obj.previous_page_number }}&search_term={{ search_form.search_term.value|default:'' }}">Vorige</a>
{% endif %}
<span class="current">
Pagina {{ page_obj.number }} / {{ paginator.num_pages }}
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}&search_term={{ search_form.search_term.value|default:'' }}">Volgende</a>
<a href="?page={{ paginator.num_pages }}&search_term={{ search_form.search_term.value|default:'' }}">Laatste »</a>
{% endif %}
</span>
</div>
- Stel
method
van het formulier in opget
om de zoekterm door te geven als URL queryparameter. - Wanneer paginering links wordt gegenereerd, voeg de huidige zoekterm (
search_form.search_term.value
) aan de URL parameters toe, zodat de zoekresultaten behouden blijven tijdens het pagineren. Gebruik de|default:''
filter om een lege string te gebruiken als er geen zoekterm is.
4. Sorteren Functie Toevoegen
Laten we een sorteerfunctie toevoegen waarmee gebruikers de gegevens kunnen sorteren volgens hun voorkeur.
4.1 Sorteren Selectieformulier Toevoegen (Optioneel)
Je kunt ook een dropdown formulier toevoegen waarmee de sorteermethode kan worden gekozen. Het kan eenvoudig worden afgehandeld via URL parameters. Hier beschrijven we de methode met URL parameters.
4.2 ListView Aanpassen
Pas de get_queryset()
methode aan door order_by()
toe te passen.
Voorbeeld van views.py (met Zoekfunctie)
from django.views.generic import ListView
from django.db.models import Q
from .models import Article
from .forms import ArticleSearchForm
class ArticleListView(ListView):
model = Article
template_name = 'articles/article_list.html'
context_object_name = 'articles'
paginate_by = 10
def get_queryset(self):
queryset = super().get_queryset()
self.form = ArticleSearchForm(self.request.GET)
ordering = self.request.GET.get('ordering', '-created_at') # Standaard sorteren: nieuwste eerst
if self.form.is_valid():
search_term = self.form.cleaned_data.get('search_term')
if search_term:
queryset = queryset.filter(
Q(title__icontains=search_term) | Q(content__icontains=search_term)
)
queryset = queryset.order_by(ordering)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['search_form'] = self.form
context['ordering'] = self.request.GET.get('ordering', '-created_at') # Huidige sorteercriteria doorgeven aan de template
return context
self.request.GET.get('ordering', '-created_at')
: Haal de waarde van deordering
parameter op uit de URL query parameters. Als deze er niet is, wordt standaard op-created_at
(nieuwste eerst) gesorteerd.queryset = queryset.order_by(ordering)
: Deze waarde wordt gebruikt om de queryset te sorteren. Door-
voor een modelveld te plaatsen, wordt het omgekeerd gesorteerd.
4.3 Sorteerlinks in de Template Aanbieden
In de template bied je links aan waarmee elke kolom kan worden gesorteerd.
Voorbeeld van articles/article_list.html
<form method="get">
{{ search_form }}
<button type="submit">Zoeken</button>
</form>
<table>
<thead>
<tr>
<th><a href="?ordering=title&search_term={{ search_form.search_term.value|default:'' }}">Titel</a></th>
<th><a href="?ordering=-created_at&search_term={{ search_form.search_term.value|default:'' }}">Datum</a></th>
</tr>
</thead>
<tbody>
{% for article in articles %}
<tr>
<td>{{ article.title }}</td>
<td>{{ article.created_at }}</td>
</tr>
{% empty %}
<tr><td colspan="2">Geen zoekresultaten gevonden.</td></tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1&search_term={{ search_form.search_term.value|default:'' }}&ordering={{ ordering }}">« Einde</a>
<a href="?page={{ page_obj.previous_page_number }}&search_term={{ search_form.search_term.value|default:'' }}&ordering={{ ordering }}">Vorige</a>
{% endif %}
<span class="current">
Pagina {{ page_obj.number }} / {{ paginator.num_pages }}
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}&search_term={{ search_form.search_term.value|default:'' }}&ordering={{ ordering }}">Volgende</a>
<a href="?page={{ paginator.num_pages }}&search_term={{ search_form.search_term.value|default:'' }}&ordering={{ ordering }}">Laatste »</a>
{% endif %}
</span>
</div>
- Voor elke tabelkop bied je een link aan met de sorteercriteria (
ordering
) parameter. - Bij het genereren van de paginering links, omvat je niet alleen de huidige zoekterm, maar ook de huidige sorteercriteria (
ordering
) in de URL parameters om de sorteertoestand te behouden tijdens het pagineren.
5. Functies Combineren met Mixin
Door het gebruik van Mixins kunnen we paging, zoek- en sorteerfunctionaliteit nog netter beheren. Bijvoorbeeld, we kunnen de zoekfunctionaliteit scheiden in een Mixin.
Voorbeeld van mixins.py
from django.db.models import Q
from .forms import ArticleSearchForm
class ArticleSearchMixin:
def get_queryset(self):
queryset = super().get_queryset()
self.form = ArticleSearchForm(self.request.GET)
if self.form.is_valid():
search_term = self.form.cleaned_data.get('search_term')
if search_term:
queryset = queryset.filter(
Q(title__icontains=search_term) | Q(content__icontains=search_term)
)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['search_form'] = getattr(self, 'form', ArticleSearchForm()) # Gebruik het standaardformulier als er geen formulier is
return context
Voorbeeld van views.py (Mixin Geïmplementeerd)
from django.views.generic import ListView
from .models import Article
from .mixins import ArticleSearchMixin
class ArticleListView(ArticleSearchMixin, ListView):
model = Article
template_name = 'articles/article_list.html'
context_object_name = 'articles'
paginate_by = 10
def get_queryset(self):
queryset = super().get_queryset()
ordering = self.request.GET.get('ordering', '-created_at')
queryset = queryset.order_by(ordering)
return queryset
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['ordering'] = self.request.GET.get('ordering', '-created_at')
return context
ArticleSearchMixin
is gemaakt om logica met betrekking tot de zoekfunctie te scheiden.ArticleListView
erft zowelArticleSearchMixin
alsListView
, waardoor het zowel zoek- als lijstfunctionaliteiten heeft.
6. Voordelen en Beperkingen van CBV (Einde van de Serie)
Door de 8 delen van de CBV-onderzoekserie hebben we de redenen onderzocht waarom we van functionele weergaven (FBV) naar klasse-gebaseerde weergaven (CBV) overschakelen, de basisstructuur en het gebruik van CBV, diverse manieren om Generic Views te gebruiken, en de uitbreiding van functies met behulp van Mixins.
Belangrijkste voordelen van CBV:
- Code herbruikbaarheid: Met Generic Views en Mixins kunnen we herhalende code verminderen en efficiënter ontwikkelen.
- Structuur van de code: Klasse-gebaseerde code maakt het gemakkelijker om de logica duidelijk te scheiden en te beheren.
- Uitbreidbaarheid: Door middel van overerving en Mixins kunnen bestaande functies eenvoudig worden uitgebreid en nieuwe functies worden toegevoegd.
- Onderhoubaarheid: De code is gemoduleerd, wat het onderhoud vergemakkelijkt en het effect van wijzigingen op de hele code minimaliseert.
- Verhoogde productiviteit van ontwikkelaars: Met de diverse Generic Views en Mixins die Django biedt, kunnen we snel ontwikkelen.
Beperkingen en aandachtspunten van CBV:
- Initiële leercurve: In vergelijking met FBV kan er een beter begrip van de klasse-gebaseerde structuur nodig zijn.
- Overmatige overerving: Het gebruik van te veel Mixins kan het moeilijk maken om de flow van de code te begrijpen. Een gepaste mate van Mixin gebruik is belangrijk.
- Over-engineering voor eenvoudige logica: Voor zeer eenvoudige pagina's of functies kan FBV overzichtelijker zijn. Het is het beste om de juiste weergavevorm te kiezen afhankelijk van de situatie.
Al met al is Django CBV een zeer krachtig en nuttig hulpmiddel voor het ontwikkelen van webapplicaties die complexe en diverse functionaliteiten vereisen. Door de voordelen van CBV te begrijpen en ze adequaat toe te passen, kunnen we efficiënter en onderhoudbare code schrijven.
Bedankt voor het lezen van de Klasse-gebaseerde weergave (CBV) onderzoekserie! We hopen dat deze serie heeft bijgedragen aan je begrip van Django CBV en dat je deze kennis kunt toepassen in je projecten.
Bekijk vorige artikelen opnieuw
- Klasse-gebaseerde weergave (CBV) Onderzoekserie #1 – De reden voor de overgang van FBV naar CBV en de houding van de ontwikkelaar
- Klasse-gebaseerde weergave (CBV) Onderzoekserie #2 – Begrijpen van de basis View-klasse van Django
- Klasse-gebaseerde weergave (CBV) Onderzoekserie #3 – Eenvoudig formulierbeheer met FormView
- Klasse-gebaseerde weergave (CBV) Onderzoekserie #4 – Gebruik van ListView & DetailView
- Klasse-gebaseerde weergave (CBV) Onderzoekserie #5 – Implementatie van CRUD met CreateView, UpdateView en DeleteView
- Klasse-gebaseerde weergave (CBV) Onderzoekserie #6 – Gebruik van TemplateView & RedirectView
- Klasse-gebaseerde weergave (CBV) Onderzoekserie #7 – Gebruik van Mixin en Toegangsbeheer
“Implementeer rijkere en gebruiksvriendelijkere lijstfunctionaliteiten door ListView uit te breiden en verbeter je Django-ontwikkelingsvaardigheden met CBV!”
댓글이 없습니다.