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>
        &ndash; {{ 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)


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow