Django
Klassenbasierte Ansichten
Suche…
Bemerkungen
Bei der Verwendung von CBV müssen wir oft genau wissen, welche Methoden wir für jede generische Klasse überschreiben können. Diese Seite der Django-Dokumentation listet alle generischen Klassen mit all ihren Methoden auf, und die Klassenattribute, die wir verwenden können.
Darüber hinaus bietet Classy Class Based View- Website dieselben Informationen mit einer interaktiven Schnittstelle.
Klassenbasierte Ansichten
Mit klassenbasierten Ansichten können Sie sich darauf konzentrieren, was Ihre Ansichten besonders macht.
Eine statische Info-Seite hat möglicherweise nichts Besonderes außer der verwendeten Vorlage. Verwenden Sie eine TemplateView ! Sie müssen lediglich einen Vorlagennamen angeben. Job erledigt. Nächster.
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'),
]
Beachten Sie, dass wir AboutView
in der URL nicht direkt AboutView
. Das liegt daran, dass ein as_view()
erwartet wird und genau das ist, was as_view()
.
Kontextdaten
Manchmal benötigt Ihre Vorlage etwas mehr Informationen. Zum Beispiel möchten wir, dass sich der Benutzer in der Kopfzeile der Seite befindet, mit einem Link zu seinem Profil neben dem Abmelde-Link. Verwenden get_context_data
in diesen Fällen die 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
Sie müssen die get_context_data-Methode für die Superklasse aufrufen. Die Standardinstanz wird zurückgegeben. Jedes Element, das Sie zu diesem Wörterbuch hinzufügen, steht der Vorlage zur Verfügung.
book.html
<h3>Active publishers</h3>
<ul>
{% for publisher in publishers %}
<li>{{ publisher.name }}</li>
{% endfor %}
</ul>
Listen- und Detailansichten
Vorlagenansichten eignen sich gut für statische Seiten, und Sie könnten sie für alles mit get_context_data
aber es wäre kaum besser als die Verwendung von Funktionen als Ansichten.
Geben Sie ListView und DetailView ein
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
Das ist alles, was Sie brauchen, um eine Ansicht zu generieren, in der alle Objekte eines Modells und Ansichten eines einzelnen Elements aufgelistet sind. Die Liste ist sogar paginiert. Sie können template_name
wenn Sie etwas Bestimmtes wünschen. Standardmäßig wird es aus dem Modellnamen generiert.
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>
Der Kontext wird mit der Objektliste unter zwei Namen, object_list
und einem zweiten Build aus dem Modellnamen, hier pokemon_list
, pokemon_list
. Wenn Sie die Liste paginiert haben, müssen Sie sich auch um den nächsten und vorherigen Link kümmern. Das Paginator- Objekt kann dabei helfen, es ist auch in den Kontextdaten verfügbar.
app / templates / app / pokemon_detail.html
<!DOCTYPE html>
<title>Pokemon {{ pokemon.name }}</title>
<h1>{{ pokemon.name }}</h1>
<h2>{{ pokemon.species }} </h2>
Der Kontext wird wie zuvor mit Ihrem pokemon
unter dem Namen object
und pokemon
, wobei das zweite vom Modellnamen abgeleitet wird.
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 diesem Snippet wird die URL für die Detailansicht mithilfe des Primärschlüssels erstellt. Es ist auch möglich, einen Slug als Argument zu verwenden. Dies gibt eine besser aussehende URL, die leichter zu merken ist. In Ihrem Modell muss jedoch ein Feld namens slug vorhanden sein.
url(r'^pokemon/(?P<slug>[A-Za-z0-9_-]+)/$', views.PokemonView.as_view(), name='pokemon'),
Wenn ein Feld namens slug
nicht vorhanden ist, können Sie die Verwendung slug_field
Einstellung in DetailView
zu einem anderen Feld zu zeigen.
Verwenden Sie zum Seitenumbruch eine Seite zum Abrufen von Parametern oder fügen Sie eine Seite direkt in die URL ein.
Formular- und Objekterstellung
Das Schreiben einer Ansicht zum Erstellen eines Objekts kann ziemlich langweilig sein. Sie müssen ein Formular anzeigen, Sie müssen es validieren, Sie müssen den Artikel speichern oder das Formular mit einem Fehler zurückschicken. Es sei denn, Sie verwenden eine der generischen Bearbeitungsansichten .
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
und UpdateView
haben zwei erforderliche Attribute, model
und fields
. Standardmäßig verwenden beide einen Vorlagennamen, der auf dem Modellnamen mit dem Zusatz '_form' basiert. Sie können nur das Suffix mit dem Attribut template_name_suffix ändern. In der DeleteView wird eine Bestätigungsmeldung angezeigt, bevor das Objekt gelöscht wird.
Sowohl UpdateView
als auch DeleteView
müssen ein Objekt DeleteView
. Sie verwenden dieselbe Methode wie DetailView
, extrahieren die Variable aus der URL und DetailView
die Objektfelder an.
app / templates / app / pokemon_form.html (extrahieren)
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
form
enthält das Formular mit allen erforderlichen Feldern. Hier wird es wegen as_p
mit einem Absatz für jedes Feld as_p
.
app / templates / app / pokemon_confirm_delete.html (extrahieren)
<form action="" method="post">
{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
<input type="submit" value="Confirm" />
</form>
Das csrf_token
Tag ist aufgrund des Django-Schutzes vor Anforderungsfälschung erforderlich. Die Attributaktion bleibt leer, da die URL, die das Formular anzeigt, mit derjenigen übereinstimmt, die das Löschen / Speichern vornimmt.
Zwei Probleme verbleiben beim Modell, wenn dieselben wie beim Listen- und Detailbeispiel verwendet werden. Erstellen und Aktualisieren beschwert sich zunächst über eine fehlende Weiterleitungs-URL. Das kann gelöst werden, indem dem pokemon-Modell ein get_absolute_url
hinzugefügt wird. Das zweite Problem ist, dass die Löschbestätigung keine aussagekräftigen Informationen anzeigt. Um dies zu lösen, besteht die einfachste Lösung darin, eine Zeichenfolgendarstellung hinzuzufügen.
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
Der Klassendekorateur sorgt dafür, dass alles unter Python 2 reibungslos funktioniert.
Minimales Beispiel
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()),
]
Erfahren Sie mehr über die Django-Dokumentation »
Django Class Based Views: Beispiel für CreateView
Mit den generischen Ansichten auf Klassenbasis ist es sehr einfach und leicht, die CRUD-Ansichten aus unseren Modellen zu erstellen. Oft ist der in Django eingebaute Admin nicht genug oder wird nicht bevorzugt und wir müssen unsere eigenen CRUD-Ansichten rollen. Die CBVs können in solchen Fällen sehr praktisch sein.
Die CreateView
Klasse benötigt drei Dinge - ein Modell, die zu verwendenden Felder und eine erfolgreiche URL.
Beispiel:
from django.views.generic import CreateView
from .models import Campaign
class CampaignCreateView(CreateView):
model = Campaign
fields = ('title', 'description')
success_url = "/campaigns/list"
Nach dem erfolgreichen Erstellen wird der Benutzer zu success_url
umgeleitet. get_success_url
können wir auch eine Methode get_success_url
definieren und reverse
oder reverse_lazy
, um die Erfolgs-URL zu erhalten.
Nun müssen wir eine Vorlage für diese Ansicht erstellen. Die Vorlage sollte im Format <app name>/<model name>_form.html
. Der Modellname muss in Großbuchstaben sein. Wenn mein App-Name beispielsweise dashboard
ist, muss ich für die obige Erstellungsansicht eine Vorlage mit dem Namen dashboard/campaign_form.html
erstellen.
In der Vorlage würde eine form
das Formular enthalten. Hier ist ein Beispielcode für die Vorlage:
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
Nun ist es Zeit, die Ansicht zu unseren URL-Mustern hinzuzufügen.
url('^campaign/new/$', CampaignCreateView.as_view(), name='campaign_new'),
Wenn wir die URL besuchen, sollte ein Formular mit den von uns ausgewählten Feldern angezeigt werden. Bei der Übergabe wird versucht, eine neue Instanz des Modells mit den Daten zu erstellen und zu speichern. Bei Erfolg wird der Benutzer zur Erfolgs-URL weitergeleitet. Bei Fehlern wird das Formular erneut mit den Fehlernachrichten angezeigt.
Eine Ansicht, mehrere Formulare
Hier ist ein schnelles Beispiel für die Verwendung mehrerer Formulare in einer Django-Ansicht.
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)