Django
Op klassen gebaseerde weergaven
Zoeken…
Opmerkingen
Bij het gebruik van CBV moeten we vaak precies weten welke methoden we voor elke generieke klasse kunnen overschrijven. Deze pagina van de django-documentatie geeft een overzicht van alle generieke klassen met al hun methoden afgeplat en de klassenattributen die we kunnen gebruiken.
Bovendien biedt de Classy Class Based View- website dezelfde informatie met een mooie interactieve interface.
Op klassen gebaseerde weergaven
Op klassen gebaseerde weergaven laten u zich concentreren op wat uw weergaven speciaal maakt.
Een statische pagina over heeft misschien niets bijzonders, behalve de gebruikte sjabloon. Gebruik een TemplateView ! Het enige wat u hoeft te doen is een sjabloonnaam instellen. Klus geklaard. De volgende.
views.py
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name = "about.html"
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url('^about/', views.AboutView.as_view(), name='about'),
]
Merk op dat we de AboutView
niet rechtstreeks AboutView
in de url. Dat komt omdat een opvraagbaar wordt verwacht en dat is precies wat as_view()
retourneert.
Context gegevens
Soms heeft uw sjabloon wat meer informatie nodig. We willen bijvoorbeeld dat de gebruiker in de koptekst van de pagina staat, met een link naar zijn profiel naast de uitloglink. Gebruik in deze gevallen de methode get_context_data
.
views.py
class BookView(DetailView):
template_name = "book.html"
def get_context_data(self, **kwargs)
""" get_context_data let you fill the template context """
context = super(BookView, self).get_context_data(**kwargs)
# Get Related publishers
context['publishers'] = self.object.publishers.filter(is_active=True)
return context
U moet de methode get_context_data aanroepen in de superklasse en deze retourneert de standaardcontextinstantie. Elk item dat u aan dit woordenboek toevoegt, is beschikbaar voor de sjabloon.
book.html
<h3>Active publishers</h3>
<ul>
{% for publisher in publishers %}
<li>{{ publisher.name }}</li>
{% endfor %}
</ul>
Lijst- en detailweergave
Sjabloonweergaven zijn prima voor statische pagina's en u kunt ze voor alles gebruiken met get_context_data
maar het zou nauwelijks beter zijn dan de functie als weergaven te gebruiken.
Ga naar ListView en DetailView
app / models.py
from django.db import models
class Pokemon(models.Model):
name = models.CharField(max_length=24)
species = models.CharField(max_length=48)
slug = models.CharField(max_length=48)
app / views.py
from django.views.generic import ListView, DetailView
from .models import Pokemon
class PokedexView(ListView):
""" Provide a list of Pokemon objects """
model = Pokemon
paginate_by = 25
class PokemonView(DetailView):
model = Pokemon
Dat is alles wat u nodig hebt om een weergave te genereren met al uw objecten van modellen en weergaven van een enkelvoudig item. De lijst is zelfs gepagineerd. U kunt template_name
als u iets specifieks wilt. Standaard wordt deze gegenereerd op basis van de modelnaam.
app / templates / app / pokemon_list.html
<!DOCTYPE html>
<title>Pokedex</title>
<ul>{% for pokemon in pokemon_list %}
<li><a href="{% url "app:pokemon" pokemon.pk %}">{{ pokemon.name }}</a>
– {{ pokemon.species }}
</ul>
De context wordt gevuld met de lijst met objecten onder twee naam, object_list
en een tweede build van de modelnaam, hier pokemon_list
. Als u de lijst hebt gepagineerd, moet u ook zorgen voor de volgende en vorige link. Het Paginator- object kan daarbij helpen, het is ook beschikbaar in de contextgegevens.
app / templates / app / pokemon_detail.html
<!DOCTYPE html>
<title>Pokemon {{ pokemon.name }}</title>
<h1>{{ pokemon.name }}</h1>
<h2>{{ pokemon.species }} </h2>
Zoals eerder wordt de context gevuld met uw modelobject onder de naam object
en pokemon
, de tweede wordt afgeleid van de modelnaam.
app / urls.py
from django.conf.urls import url
from . import views
app_name = 'app'
urlpatterns = [
url(r'^pokemon/$', views.PokedexView.as_view(), name='pokedex'),
url(r'^pokemon/(?P<pk>\d+)/$', views.PokemonView.as_view(), name='pokemon'),
]
In dit fragment wordt de url voor de detailweergave opgebouwd met de primaire sleutel. Het is ook mogelijk om een slak als argument te gebruiken. Dit geeft een mooiere url die gemakkelijker te onthouden is. Het vereist echter de aanwezigheid van een veld met de naam slug in uw model.
url(r'^pokemon/(?P<slug>[A-Za-z0-9_-]+)/$', views.PokemonView.as_view(), name='pokemon'),
Als een veld genaamd slug
niet aanwezig is, kunt u het gebruik slug_field
instelling in DetailView
te wijzen op een ander veld.
Gebruik voor paginering een parameter voor het ophalen van pagina's of plaats een pagina rechtstreeks in de URL.
Vorm- en objectcreatie
Het schrijven van een weergave om een object te maken, kan behoorlijk saai zijn. U moet een formulier weergeven, u moet het valideren, u moet het item opslaan of het formulier met een fout retourneren. Tenzij u een van de generieke bewerkingsweergaven gebruikt .
app / views.py
from django.core.urlresolvers import reverse_lazy
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from .models import Pokemon
class PokemonCreate(CreateView):
model = Pokemon
fields = ['name', 'species']
class PokemonUpdate(UpdateView):
model = Pokemon
fields = ['name', 'species']
class PokemonDelete(DeleteView):
model = Pokemon
success_url = reverse_lazy('pokedex')
CreateView
en UpdateView
hebben twee vereiste attributen, model
en fields
. Beide gebruiken standaard een sjabloonnaam op basis van de modelnaam met '_form'. U kunt alleen het achtervoegsel wijzigen met het kenmerk template_name_suffix. De DeleteView toont een bevestigingsbericht voordat het object wordt verwijderd.
Zowel UpdateView
als DeleteView
moeten op object worden DeleteView
. Ze gebruiken dezelfde methode als DetailView
, waarbij ze variabele uit de URL extraheren en overeenkomen met de objectvelden.
app / templates / app / pokemon_form.html (extract)
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
form
bevat het formulier met alle benodigde velden. Hier wordt het weergegeven met een alinea voor elk veld vanwege as_p
.
app / templates / app / pokemon_confirm_delete.html (extract)
<form action="" method="post">
{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
<input type="submit" value="Confirm" />
</form>
De csrf_token
tag is vereist vanwege django-bescherming tegen vervalsing van aanvragen. De attribuutactie blijft leeg omdat de url die het formulier weergeeft hetzelfde is als degene die de verwijdering / opslag uitvoert.
Er blijven twee problemen met het model bestaan, als hetzelfde wordt gebruikt als met de lijst en het voorbeeld. Eerst maken en bijwerken zal klagen over een ontbrekende omleidings-URL. Dat kan worden opgelost door een get_absolute_url
te voegen aan het pokemon-model. Tweede probleem is de verwijderingbevestiging die geen betekenisvolle informatie weergeeft. Om dit op te lossen, is de eenvoudigste oplossing een stringvoorstelling toe te voegen.
app / models.py
from django.db import models
from django.urls import reverse
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class Pokemon(models.Model):
name = models.CharField(max_length=24)
species = models.CharField(max_length=48)
def get_absolute_url(self):
return reverse('app:pokemon', kwargs={'pk':self.pk})
def __str__(self):
return self.name
De klassedecorateur zorgt ervoor dat alles soepel werkt onder python 2.
Minimaal voorbeeld
views.py :
from django.http import HttpResponse
from django.views.generic import View
class MyView(View):
def get(self, request):
# <view logic>
return HttpResponse('result')
urls.py :
from django.conf.urls import url
from myapp.views import MyView
urlpatterns = [
url(r'^about/$', MyView.as_view()),
]
Meer informatie over Django-documentatie »
Op Django-klasse gebaseerde weergaven: voorbeeld van CreateView
Met de op klassen gebaseerde generieke weergaven is het heel eenvoudig en gemakkelijk om de CRUD-weergaven op basis van onze modellen te maken. Vaak is de ingebouwde Django-beheerder niet genoeg of niet de voorkeur en moeten we onze eigen CRUD-weergaven maken. De CBV's kunnen in dergelijke gevallen erg handig zijn.
De klasse CreateView
heeft 3 dingen nodig - een model, de te gebruiken velden en de succes-URL.
Voorbeeld:
from django.views.generic import CreateView
from .models import Campaign
class CampaignCreateView(CreateView):
model = Campaign
fields = ('title', 'description')
success_url = "/campaigns/list"
Zodra het creëren is geslaagd, wordt de gebruiker omgeleid naar success_url
. We kunnen in plaats daarvan ook een methode get_success_url
definiëren en reverse
of reverse_lazy
gebruiken om de succes-URL te krijgen.
Nu moeten we een sjabloon maken voor deze weergave. De sjabloon moet een naam hebben in het formaat <app name>/<model name>_form.html
. De modelnaam moet in kleine letters zijn. Als mijn app-naam bijvoorbeeld dashboard
, moet ik voor de bovenstaande weergave maken een sjabloon met de naam dashboard/campaign_form.html
.
In de sjabloon zou een form
het formulier bevatten. Hier is een voorbeeldcode voor de sjabloon:
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
Nu is het tijd om de weergave toe te voegen aan onze URL-patronen.
url('^campaign/new/$', CampaignCreateView.as_view(), name='campaign_new'),
Als we de URL bezoeken, zien we een formulier met de velden die we hebben gekozen. Wanneer we indienen, probeert het een nieuw exemplaar van het model met de gegevens te maken en op te slaan. Bij succes wordt de gebruiker omgeleid naar de succes-URL. Bij fouten wordt het formulier opnieuw weergegeven met de foutmeldingen.
Eén weergave, meerdere formulieren
Hier is een snel voorbeeld van het gebruik van meerdere formulieren in één Django-weergave.
from django.contrib import messages
from django.views.generic import TemplateView
from .forms import AddPostForm, AddCommentForm
from .models import Comment
class AddCommentView(TemplateView):
post_form_class = AddPostForm
comment_form_class = AddCommentForm
template_name = 'blog/post.html'
def post(self, request):
post_data = request.POST or None
post_form = self.post_form_class(post_data, prefix='post')
comment_form = self.comment_form_class(post_data, prefix='comment')
context = self.get_context_data(post_form=post_form,
comment_form=comment_form)
if post_form.is_valid():
self.form_save(post_form)
if comment_form.is_valid():
self.form_save(comment_form)
return self.render_to_response(context)
def form_save(self, form):
obj = form.save()
messages.success(self.request, "{} saved successfully".format(obj))
return obj
def get(self, request, *args, **kwargs):
return self.post(request, *args, **kwargs)