[PYTHON] Erste Schritte und Verwendung von auf Klassenklassen basierenden generischen Ansichten in Django

Wenn Sie Fehler oder Missverständnisse haben, weisen Sie bitte darauf hin.

Warum diesen Artikel schreiben?

Django hat eine mächtige Vorlagensprache.

Es ist die Ansicht, die die Daten an die Vorlage liefert. Und es gibt auch eine schnelle Möglichkeit, es zu codieren. Das ist die "generische Ansicht".

Es scheint, dass wir vor langer Zeit funktionsbasierte generische Ansichten verwendet haben, aber jetzt verwenden wir hauptsächlich klassenbasierte Ansichten. Die aktuelle japanische Übersetzung von Django ist 1.4, es gibt jedoch ein klassenbasiertes generisches Ansichtsdokument.

http://docs.djangoproject.jp/en/latest/topics/class-based-views.html

Es gab jedoch weniger Artikel, in denen klassenbasierte allgemeine Ansichten erläutert wurden, als ich erwartet hatte, und ich beschloss, sie aufzuschreiben.

Inhalt dieses Artikels

Was ist eine generische Ansicht

Die Ansicht ist der Controller in Rails. Django scheint es Ansicht zu nennen, weil es auf der Idee von MTV (Modell, Vorlage, Ansicht) basiert.

Es ist verantwortlich für die Bereitstellung der Daten für die Vorlage, aber die meisten Websites

Es hat eine Funktion namens. Der Prozess wird im Voraus in Django definiert, sodass Sie nicht oft ähnlichen Code schreiben müssen.

Sie werden als "Allzweckansichten" bezeichnet. Wenn sie von einer Funktion bereitgestellt werden, werden sie als "funktionsbasierte Allzweckansichten" bezeichnet. Wenn sie von einer Klasse bereitgestellt werden, werden sie als "klassenbasierte Allzweckansichten" bezeichnet.

In der allgemeinen Ansicht wird der entsprechende Standardwert entsprechend dem Modell, der Form usw. festgelegt. Daher hat es den Vorteil, dass der vom Programmierer geschriebene Betrag sehr gering ist.

Dieser Artikel enthält Hinweise zu "klassenbasierten generischen Ansichten".

Klassenbasierte generische Ansichten definieren eine ähnliche Verarbeitung für jede Klasse. Wir können von dieser Klasse erben, Klassenvariablen bei Bedarf ändern und Methoden überschreiben, um unsere eigene Verarbeitung einzufügen.

Verwendung der klassenbasierten generischen Ansicht

Erster Schritt

** Dies ist der erste Schritt, also konzentrieren wir uns darauf, wie man es schreibt. ** ** **

Generische Ansichten werden hauptsächlich in views.py usw. verwendet. Verknüpfen Sie die URL außerdem mit der Funktion "as_view ()" in "urls.py".

Lassen Sie uns ein Beispiel schreiben. Angenommen, Sie haben ein Projekt mit django-admin usw. erstellt und eine Anwendung als manager.py startapp foo erstellt.

Nun, ich werde schreiben.

foo/views.py


from django.views.generic import TemplateView

class SampleTemplateView(TemplateView):
    template_name = "index.html"

Es ist jetzt einsatzbereit. Sie können sehen, dass die Menge der Beschreibung sehr gering ist.

Hier ist "TemplateView" eine generische Ansicht. Ansichten werden für jeden Zweck in django.views.generic usw. vorbereitet, also importieren und erben.

URL ist

urls.py


from foo.views import SampleTemplateView

urlpatterns = [
    url(r'^sample$', SampleTemplateView.as_view()),
]

Wenn ja, wird SampleTemplateView beim Zugriff auf / sample gut damit umgehen.

Auf diese Weise können Sie die Menge an Code, die Sie in "views.py" schreiben, drastisch reduzieren. Wie der Name schon sagt, soll "TemplateView" mit einer Vorlage gezeichnet werden. Wenn Sie anstelle von "TemplateView" eine andere Allzweckansicht verwenden, können Sie die Liste anzeigen, ohne den Code zu schreiben, um die Daten aus der Datenbank abzurufen, oder Sie können die Daten ausgeben, nachdem Sie sie durch bestimmte Bedingungen eingegrenzt haben.

Ich möchte die von mir festgelegten Variablen an die Vorlage übergeben

Im ersten Schritt konnte ich nur die Vorlage anzeigen. In der Regel möchten Sie jedoch die aus der Datenbank gelesenen Daten anzeigen.

Überschreiben Sie in diesem Fall die in der generischen Ansicht definierte Methode.

Die Methode, die ich oft überschreibe, ist "get_context_data".

Verwenden Sie es wie folgt.

views.py


from django.views.generic import TemplateView


class SampleTemplate(TemplateView):

    template_name = "index.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs) #Rufen Sie zuerst die geerbte Methode auf
        context["foo"] = "bar"
        return context

Verwenden Sie wie.

Im obigen Code können Sie mit der Vorlage eine Variable namens "foo" verwenden. Wenn Sie in der Vorlage "{{foo}}" verwenden, wird "bar" angezeigt.

Wenn der Dateiname der Vorlage "index.html" usw. lautet.

index.html


<div class="sample">{{ foo }}</div>

angesichts dessen,

index.html


<div class="sample">bar</div>

Es bedeutet das.

Mit anderen Worten, wenn Sie den Prozess beschreiben, den Sie in diese Methode einfügen möchten, und ihn in den Rückgabewert von "get_context_data" einfügen, können Sie ihn in der Vorlage verwenden.

Dieses Kapitel Zusammenfassung

Auf diese Weise können Sie die Methode in der allgemeinen Ansicht überschreiben und die erforderliche Verarbeitung hinzufügen. Dies ist die Grundverwendung.

Es gibt viele nützliche Allzweckansichten wie "ListView" zum Anzeigen einer Liste und "DetailView" zum Erstellen einzelner Seiten, daher werde ich sie vorstellen.

Klassenbasierte generische Ansichtstypen (teilweise)

** Hinweis: Nicht alle werden hier vorgestellt **

https://github.com/django/django/blob/master/django/views/generic/init.py

Wenn Sie sich das ansehen, werden viele weitere allgemeine Ansichten definiert, z. B. "RedirectView" und "FormView".

TemplateView

Wie der Name schon sagt, ist "TemplateView" eine Allzweckansicht, in der durch Angabe einer Vorlage etwas angezeigt wird. Daher muss der Vorlagenname angegeben werden.

Es ruft auch "get_context_data" auf, überschreibt und setzt die erforderlichen Daten. Natürlich liegt es außerhalb der Kontrolle der allgemeinen Ansicht, daher müssen Sie die Zählung und Filterung selbst durchführen.

views.py


from django.views.generic import TemplateView


class MyTemplateView(TemplateView):

    template_name = "index.html"  #Verpflichtend

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        #Mach verschiedene Dinge
        return context

Der Autor verwendet es hauptsächlich auf der obersten Seite der Website.

ListView

https://docs.djangoproject.com/ja/1.9/ref/class-based-views/generic-display/#listview

Wie der Name schon sagt, wird beim Erstellen von Listenseiten "ListView" verwendet.

Wenn Sie einfach eine Liste von Zielmodellen erstellen,

views.py


from django.views.generic import ListView
from foo.model import MyModel

class MyListView(ListView):

    model = MyModel

Es ist definiert als. model = MyModel ist das Modell, das die Liste erstellt.

Die Vorlage würde so aussehen.

mymodel/mymodel_list.html


<ul>
  {% for item in object_list %}
  <li>{{ item }}</li>
  {% endfor %}
</ul>

Selbst wenn die Datenbank viele Daten enthält, teilt ListView die Liste standardmäßig um 10 </ s> (geändert durch Hinweis im Kommentar), aber alle Elemente werden erfasst, jedoch die später beschriebenen Variablen Mit können Sie die Anzahl der auf einer Seite ausgegebenen Elemente steuern. Die zu teilende Zahl ist eine Variable namens "paginate_by".

Mit anderen Worten, wenn Sie 5 Fälle gleichzeitig teilen möchten

views.py


class MyListView(ListView):
    model = MyModel
    paginate_by = 5

Ist definiert als.

Dies ist eine Einstellung, bei der bei 100 Daten nur 5 auf einer Seite angezeigt werden.

Manchmal möchten Sie auch die Sortierreihenfolge der zu erfassenden Daten im Voraus ändern oder sie filtern und steuern. In diesem Fall überschreiben Sie die Methode "get_queryset".

views.py


class MyListView(ListView):
    model = MyModel
    paginate_by = 5

    def get_queryset(self):
        return MyModel.objects.filter(some_column=foo)

Machen. Dann wird die durch "get_queryset" definierte Abfrage ausgegeben und die Daten in "object_list" gespeichert.

Wenn Sie die Anzahl der zu extrahierenden Elemente in der Liste begrenzen möchten, geben Sie hier an.

Die Bezeichnung ist eine normale Scheibe.

views.py



def get_queryset(self, queryset=None):
    return MyModel.objects.all()[:10]

Selbst wenn 100 Datenelemente vorhanden sind, werden damit nur 10 Elemente extrahiert.

Diese Schrift kann etwas kürzer sein.

views.py


class MyListView(ListView):
    model = MyModel
    paginate_by = 5
    queryset = MyModel.objects.filter(some_column=foo)

Unabhängig davon, was Sie verwenden, ändert sich das Ergebnis nicht.

Wenn Sie Abfragen dynamisch ausgeben möchten, verwenden Sie die erstere, und wenn Sie immer das gleiche Ergebnis erzielen möchten, verwenden Sie die letztere.

Natürlich können Sie Daten aus anderen Tabellen an die Vorlage übergeben, indem Sie die Methode "get_context_data" überschreiben.

views.py


class MyListView(ListView):
    model = MyModel
    paginate_by = 5

    def get_queryset(self):
        return MyModel.objects.filter(some_column=foo)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**data)
        context["bar"] = OtherModel.objects.all()  #Holen Sie sich Daten von anderen Modellen
        return context

In diesem Fall wird "OtherModel" jedoch nicht von der generischen Ansicht gesteuert, sodass "context [" bar "]" die gesamte Anzahl von "OtherModel" speichert.

DetailView

https://docs.djangoproject.com/ja/1.9/ref/class-based-views/generic-display/#detailview

Wie der Name schon sagt, ist "DetailView" eine Allzweckansicht für einzelne Detailseiten. Erfasst Daten für eine einzelne Datensatzzeile.

views.py



from django.views.generic import DetailView
from mymodel.model import MyModel


class MyDetailView(DetailView):
    model = MyModel

URL ist

urls.py


urlpatterns = [
    url(r'^(?P<pk>\d+)$', MyDetailView.as_view()),
]

Wird besorgt. pk ist der Primärschlüssel, aber DetailView verwendet diesen Namen, um den Datensatz zu identifizieren. Sie können es ändern, aber wenn Sie es nicht benötigen, können Sie es so lassen, wie es ist.

CreateView / UpdateView

https://docs.djangoproject.com/ja/1.9/ref/class-based-views/generic-editing/#django.views.generic.edit.CreateView

CreateView ist eine Ansicht, die ein Formular zum Hinzufügen eines neuen Datensatzes bereitstellt. Wie zu erwarten, ist "UpdateView" eine Ansicht, die ein Formular zum Aktualisieren vorhandener Daten bereitstellt.

views.py


from django.views.generic.edit import CreateView

class MyCreateView(CreateView):
    model = MyModel
    fields = ("name", )  #Liste oder Taple

Definieren Sie es so. Es unterscheidet sich nicht wesentlich von anderen allgemeinen Ansichten. Sie müssen jedoch eine Variable mit dem Namen "Felder" in "CreateView" und "UpdateView" definieren. Dies bedeutet, dass Daten, die aus dem Formular eingegeben werden, mit Ausnahme der in "Felder" definierten Felder ignoriert werden. Ist es so etwas wie starke Parameter in Schienen?

Der Unterschied zwischen "CreateView" und "UpdateView" zu anderen generischen Ansichten besteht darin, dass sie "ein Formular erstellen". Das heißt, es wird eine Variable namens "form" anstelle von "object" oder "object_list" erstellt.

Die Variable form enthält Daten zum Erstellen eines Formulars, wodurch das Erstellen eines Formulars vereinfacht wird.

Hier ist eine Vorlage, die die Variable form verwendet.

<form method="post">
    {% csrf_token %}
    <table>
        {{ form }}
    </table>
    <input type="submit">
</form>

Sie müssen das HTML-Tag "

</ form>" selbst schreiben, aber die Formularfelder werden für Sie generiert. Standardmäßig gibt {{form}} Felder mithilfe von Tabellen aus. Wenn Sie ein Feld mit dem Tag "

</ p>" erstellen möchten, verwenden Sie "{{form.as_p}}".

{% csrf_token%} ist eine CSRF-Kennzahl. Erforderlich, wenn Sie mit Django ein POST-Formular usw. erstellt haben.

https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3%82%A4%E3%83%88%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%AA

http://docs.djangoproject.jp/en/latest/ref/contrib/csrf.html

Sie können auch Formularobjekte wie "ModelForm" verwenden.

Auf diese Weise können Sie Ihre vorhandenen Formularklassen problemlos nutzen.

forms.py


from django import forms
from myapp.model import MyModel

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ("name", )

views.py


from forms import MyModelForm

class MyCreateView(CreateView):
    form_class = MyModelForm

Die Validierung ist auch ein wichtiges Merkmal dieser Formulare. Selbst wenn Sie das Formular mit großem Aufwand senden und ein Fehler bei der Validierung auftritt und es nicht hinzugefügt oder aktualisiert wird, kann es verwirrend sein, wenn Sie den Benutzer nicht benachrichtigen.

Daher werden in diesen allgemeinen Ansichten die Methoden form_valid und form_invalid definiert, und Sie können die erforderliche Verarbeitung ausführen, je nachdem, ob die Validierung bestanden wurde oder nicht.

Beispielsweise wird Benutzern häufig mitgeteilt, ob das von ihnen übermittelte Formular erfolgreich gespeichert wurde. Zu diesem Zeitpunkt verwendet Django das Nachrichten-Framework.

http://docs.djangoproject.jp/en/latest/ref/contrib/messages.html

views.py


from django.views.generic.edit import CreateView
from django.contrib import messages  #Nachrichten-Framework

from myapp.models import MyModel


class MyCreateView(CreateView):
    model = MyModel

    def form_valid(self, form):
        '''Nach bestandener Validierung'''
        messages.success(self.request, "Gerettet")
        return super().form_valid(form)

    def form_invalid(self, form):
        '''Wenn die Validierung fehlschlägt'''
        message.warning(self.request, "Konnte nicht speichern")
        return super().form_invalid(form)

Hier haben wir unsere eigenen Nachrichten zur Methode "form_valid" hinzugefügt, die aufgerufen wird, wenn die Validierung erfolgreich ist, und zur Methode "form_invalid", die aufgerufen wird, wenn die Validierung nicht erfolgreich ist.

Auf diese Weise können Sie Ihre eigene Verarbeitung hinzufügen. Zusätzlich zum obigen Beispiel können Sie eine Verarbeitung einfügen, z. B. den Administrator per E-Mail benachrichtigen, wenn ein Fehler auftritt.

Wenn Sie mit Ihrer eigenen Verarbeitung fertig sind, rufen Sie die Vererbungsmethode auf und geben Sie den Rückgabewert zurück.

Übrigens, um die Nachricht anzuzeigen, gehen Sie wie folgt vor. Der Inhalt des Dokuments ist so wie es ist.

{% if messages %}
<ul class="messages">
    {% for message in messages %}
    <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}

DeleteView

Wie der Name schon sagt, löscht "DeleteView" einen Datensatz. Die Vorlage lautet "(AppName) / (AppName) _confirm_delete.html".

views.py


from django.views.generic.edit import DeleteView
from myapp.models import MyModel


class MyDeleteView(DeleteView):
    model = MyModel

In diesem Fall handelt es sich bei der Vorlage um ein Bestätigungsformular mit der Frage "Möchten Sie es wirklich löschen?".

Vielleicht gibt es Zeiten, in denen Sie nur das Löschflag aktivieren möchten, anstatt es wirklich zu löschen. In einem solchen Fall ist es besser, die Löschmethode zu überschreiben. Ich habe es jedoch nicht ausprobiert, weil ich es gehorsam lösche.

Gemeinsame Gegenstände

Zusätzlich zur oben genannten Verarbeitung kann die klassenbasierte Allzweckansicht den Namen der Vorlagendatei und den Variablennamen frei überschreiben. Darüber hinaus ist die Methode auch üblich, daher werde ich einige vorstellen. Ich denke, es ist normalerweise am besten, den Standardwert zu verwenden und ihn nur bei Bedarf zu überschreiben.

Standardvariable

Wie Sie vielleicht bereits bemerkt haben, haben generische Ansichten eine gewisse Regelmäßigkeit. Im ersten Schritt wurde das Überschreiben von get_context_data, das Ausführen der erforderlichen Verarbeitung und das Festlegen in einer Variablen eingeführt. Wenn Sie Daten an eine Vorlage übergeben möchten, sollte dies ausreichen.

Im Gegenteil, wenn eine Allzweckansicht automatisch Daten abruft, welche Art von Daten wird in welcher Variablen festgelegt?

Die klassenbasierte generische Ansicht ruft automatisch Daten aus der Datenbank entsprechend ihrer beabsichtigten Verwendung ab (erbende Klasse). Legen Sie fest, aus welcher Tabelle die Daten als model = MyModel abgerufen werden sollen.

views.py


class MyListView(ListView):
    model = MyModel  #Holen Sie sich automatisch eine Liste von MyModels

Auf diese Weise erhalten Sie die Daten von "MyModel". Das Ergebnis usw. soll in einer Variablen mit festem Namen gesetzt werden. "Objekt", wenn nur ein Datensatz vorhanden ist, z. B. eine einzelne Seite. Object_list wenn es mehr als eine gibt.

Die Vorlage würde folgendermaßen aussehen:

Einzelne Seiten etc.

{{ object }}

Wenn es mehrere gibt

{% for item in object_list %}
  {{ item }}
{% endfor %}

Ich kann jedoch anhand der Vorlage nicht sagen, was dies bedeutet. Möglicherweise möchten Sie den Variablennamen aussagekräftiger gestalten. Weisen Sie in diesem Fall den Variablennamen context_object_name zu.

views.py


class MyBookList(ListView):
    model = Books
    context_object_name = "my_books"  #Geben Sie den Variablennamen in diese Zeile ein

Auf diese Weise in der Vorlage

<ul>
    {% for book in my_books %}
    <li>{{ book.name }}</li>
    {% endfor %}
</ul>

Sie können es so nennen. Nachdem Sie nun wissen, worauf sich der Variablenname bezieht, können Sie leicht erkennen, worauf sich die Variable bezieht, indem Sie einfach die Vorlage lesen.

Angabe der Datei, die als Vorlage verwendet werden soll

Ansichten sind Controller. Übergeben Sie daher die Daten an die entsprechende Vorlage. Die Vorlage kann explizit angegeben werden, hat jedoch einen Standardvorlagennamen. das ist,

(ModelName)/(ModelName)_(ViewName).html

Das ist.

Sie sind,

  • AppName
  • Der Name der Anwendung, die von manage.py startapp usw. erstellt wurde.
  • ViewName
  • Eindeutige Namen wie "Liste" für "ListView" und "Detail" für "DetailView"

Es sollte sein. Das heißt, wenn Sie "ListView" mit "myapp" verwenden, wird standardmäßig nach "myapp / myapp_list.html" gesucht.

Wenn Sie dies ändern möchten

views.py


class MyListView(ListView):
    model = MyModel
    template_name = "my_list_view.html"  #Geben Sie die Vorlage in dieser Zeile an

Machen.

Beiseite

Wenn Sie eine generische Ansicht verwenden, möchten Sie in jeder Ansicht dieselbe Variable definieren. Zum Beispiel "Site-Name". Es ist nicht gut, es in allen Ansichten zu definieren, daher frage ich mich, ob ich eine gemeinsame Klasse erstellen und sie erben soll.

base_view.py


from django.views.generic import ListView

from myapp.models import MyModel


#Erben Sie nicht Mixin usw., sondern das Objekt.
class MyCommonView(object):

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["SITE_NAME"] = "SITE-NAME"
        return context


class MyListView(ListView, MyCommonView):
    model = MyModel

Wenn Sie den Site-Namen ändern möchten, müssen Sie ihn nur an einer Stelle ändern ...? Das wäre eine Möglichkeit, aber ich denke, es ist besser, den Kontextprozessor gehorsam zu verwenden.

Nachwort

Ich bin müde.

Ich hoffe, es wird denen helfen, die Django benutzen.

Vorerst

  • Django 1.9
  • python 3.5.1

Ich habe die Operation mit bestätigt, aber bitte sagen Sie mir, wenn etwas nicht stimmt.

Recommended Posts