Szukaj…


Uwagi

Podczas korzystania z CBV często musimy dokładnie wiedzieć, jakie metody możemy zastąpić dla każdej klasy ogólnej. Ta strona dokumentacji django zawiera listę wszystkich klas ogólnych wraz ze spłaszczonymi metodami oraz atrybutami klas, których możemy użyć.

Ponadto strona internetowa Classy Class Based View zapewnia te same informacje z ładnym interaktywnym interfejsem.

Widoki klasowe

Widoki oparte na klasach pozwalają skupić się na tym, co czyni Twoje widoki wyjątkowymi.

Statyczne informacje o stronie mogą nie mieć nic specjalnego oprócz użytego szablonu. Użyj TemplateView ! Wszystko, co musisz zrobić, to ustawić nazwę szablonu. Zadanie wykonane. Kolejny.

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'),
]

Zauważ, że nie używamy bezpośrednio AboutView w AboutView URL. Jest tak, ponieważ oczekuje się as_view() i właśnie to as_view() .

Dane kontekstowe

Czasami twój szablon potrzebuje trochę więcej informacji. Na przykład chcielibyśmy mieć użytkownika w nagłówku strony, z linkiem do jego profilu obok linku wylogowania. W takich przypadkach użyj metody 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

Musisz wywołać metodę get_context_data dla superklasy, a ona zwróci domyślną instancję kontekstu. Każdy element dodany do tego słownika będzie dostępny w szablonie.

book.html

<h3>Active publishers</h3>
<ul>
  {% for publisher in publishers %}
    <li>{{ publisher.name }}</li>
  {% endfor %}
</ul>

Widoki listy i szczegółów

Widoki szablonów są odpowiednie dla stron statycznych i można ich używać do wszystkiego z get_context_data ale byłoby to niewiele lepsze niż używanie funkcji jako widoków.

Wejdź w ListView i 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

To wszystko, czego potrzebujesz, aby wygenerować widok z listą wszystkich obiektów modeli i widoków pojedynczego elementu. Lista jest nawet paginowana. Możesz podać template_name jeśli chcesz coś konkretnego. Domyślnie jest generowany na podstawie nazwy modelu.

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>

Kontekst jest wypełniony listą obiektów pod dwiema nazwami, object_list i drugą object_list z nazwy modelu, tutaj pokemon_list . Jeśli paginujesz listę, musisz również zadbać o następny i poprzedni link. Obiekt Paginator może w tym pomóc, jest również dostępny w danych kontekstowych.

app / templates / app / pokemon_detail.html

<!DOCTYPE html>
<title>Pokemon {{ pokemon.name }}</title>
<h1>{{ pokemon.name }}</h1>
<h2>{{ pokemon.species }} </h2>

Tak jak poprzednio, kontekst jest zapełniany obiektem modelu pod nazwą object i pokemon , przy czym drugi pochodzi od nazwy modelu.

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'),
]

W tym fragmencie adres URL widoku szczegółowego jest tworzony przy użyciu klucza podstawowego. Można również użyć ślimaka jako argumentu. Daje to ładniej wyglądający adres URL, który jest łatwiejszy do zapamiętania. Wymaga to jednak obecności w twoim polu pola o nazwie ślimak.

url(r'^pokemon/(?P<slug>[A-Za-z0-9_-]+)/$', views.PokemonView.as_view(), name='pokemon'),

Jeśli pole zwany slug nie jest obecny, można użyć slug_field ustawienia w DetailView do punktu na innym polu.

Do paginacji użyj parametrów pobierania strony lub umieść stronę bezpośrednio w adresie URL.

Tworzenie formularzy i obiektów

Pisanie widoku w celu stworzenia obiektu może być dość nudne. Musisz wyświetlić formularz, musisz go zweryfikować, musisz zapisać element lub zwrócić formularz z błędem. Chyba że użyjesz jednego z ogólnych widoków edycji .

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 i UpdateView mają dwa wymagane atrybuty, model i fields . Domyślnie oba używają nazwy szablonu opartej na nazwie modelu z przyrostkiem „_form”. Możesz zmienić tylko przyrostek za pomocą atrybutu nazwa_szablonu_sufiks. DeleteView pokazuje komunikat potwierdzający przed usunięciem obiektu.

Zarówno UpdateView jak i DeleteView muszą pobierać na obiekcie. Używają tej samej metody co DetailView , wydobywając zmienną z DetailView URL i dopasowując pola obiektu.

app / templates / app / pokemon_form.html (rozpakuj)

<form action="" method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Save" />
</form>

form zawiera formularz ze wszystkimi potrzebnymi polami. Tutaj będzie wyświetlany akapit dla każdego pola z powodu as_p .

app / templates / app / pokemon_confirm_delete.html (rozpakuj)

<form action="" method="post">
    {% csrf_token %}
    <p>Are you sure you want to delete "{{ object }}"?</p>
    <input type="submit" value="Confirm" />
</form>

Tag csrf_token jest wymagany ze względu na ochronę django przed fałszowaniem żądań. Akcja atrybutu pozostaje pusta, ponieważ adres URL wyświetlający formularz jest taki sam, jak adres obsługujący usuwanie / zapisywanie.

Z modelem pozostają dwa problemy, jeśli używasz go tak samo jak z listą i przykładami szczegółów. Po pierwsze, tworzenie i aktualizacja będą narzekać na brakujący adres przekierowania. Można to rozwiązać, dodając get_absolute_url do modelu get_absolute_url . Drugi problem to potwierdzenie usunięcia, które nie wyświetla istotnych informacji. Aby rozwiązać ten problem, najłatwiejszym rozwiązaniem jest dodanie reprezentacji ciągu.

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

Dekorator klasy upewni się, że wszystko działa poprawnie w Pythonie 2.

Minimalny przykład

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()),
]

Dowiedz się więcej o dokumentacji Django »

Widoki oparte na klasach Django: Przykład CreateView

Dzięki widokom ogólnym opartym na klasach tworzenie widoków CRUD z naszych modeli jest bardzo proste i łatwe. Często wbudowany administrator Django nie jest wystarczający lub nie jest preferowany i musimy stworzyć własne widoki CRUD. W takich przypadkach CBV mogą być bardzo przydatne.

Klasa CreateView potrzebuje 3 rzeczy - modelu, pól do użycia i CreateView URL sukcesu.

Przykład:

from django.views.generic import CreateView 
from .models import Campaign

class CampaignCreateView(CreateView):
    model = Campaign
    fields = ('title', 'description')
    
    success_url = "/campaigns/list"

Po pomyślnym utworzeniu użytkownik zostaje przekierowany na success_url . Możemy również zdefiniować metodę get_success_url zamiast tego i użyć reverse lub reverse_lazy aby uzyskać adres URL sukcesu.

Teraz musimy utworzyć szablon dla tego widoku. Szablon powinien mieć nazwę <app name>/<model name>_form.html . Nazwa modelu musi być zapisana małymi literami. Na przykład, jeśli nazwa mojej aplikacji to dashboard , to dla powyższego widoku tworzenia muszę utworzyć szablon o nazwie dashboard/campaign_form.html .

W szablonie zmienna form zawierałaby formularz. Oto przykładowy kod szablonu:

<form action="" method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Save" />
</form>            

Czas dodać widok do naszych wzorców adresów URL.

url('^campaign/new/$', CampaignCreateView.as_view(), name='campaign_new'),

Jeśli odwiedzimy adres URL, powinniśmy zobaczyć formularz z wybranymi polami. Po przesłaniu spróbuje utworzyć nową instancję modelu z danymi i zapisać ją. Po sukcesie użytkownik zostanie przekierowany do adresu URL sukcesu. W przypadku błędów formularz zostanie wyświetlony ponownie z komunikatem o błędzie.

Jeden widok, wiele formularzy

Oto szybki przykład użycia wielu formularzy w jednym widoku Django.

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow