Sök…


Anmärkningar

När vi använder CBV behöver vi ofta veta exakt vilka metoder vi kan skriva över för varje generisk klass. Denna sida med django-dokumentationen visar alla generiska klasser med alla sina metoder plattade och klassattribut som vi kan använda.

Dessutom ger webbplatsen Classy Class Based View samma information med ett trevligt interaktivt gränssnitt.

Klassbaserade vyer

Klassbaserade vyer låter dig fokusera på det som gör dina åsikter speciella.

En statisk sida om sidan kanske inte har något speciellt, förutom den använda mallen. Använd en mallvy ! Allt du behöver göra är att ange ett mallnamn. Jobbet färdig. Nästa.

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

Lägg märke till hur vi inte använder direkt AboutView i url- AboutView . Det beror på att en kalkylbar förväntas och det är exakt vad as_view() returnerar.

Kontextdata

Ibland behöver din mall lite mer information. Vi vill till exempel ha användaren i sidhuvudet med en länk till sin profil bredvid utloggningslänken. I dessa fall använder get_context_data metoden 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

Du måste ringa metoden get_context_data i superklassen och den kommer att returnera standardkontextinstansen. Alla objekt som du lägger till i denna ordlista kommer att vara tillgängliga för mallen.

book.html

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

Listor och detaljer

Mallvyer är bra för statisk sida och du kan använda dem för allt med get_context_data men det skulle knappt vara bättre än att använda funktion som vyer.

Ange ListView och 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

Det är allt du behöver för att skapa en vy där alla dina objekt för modeller och vyer av enskilda objekt visas. Listan är till och med paginerad. Du kan ange template_name om du vill ha något specifikt. Som standard genereras det från modellnamnet.

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>

Kontextet fylls med listan över objekt under två namn, object_list och en andra bygger från modellnamnet, här pokemon_list . Om du har paginerat listan måste du ta hand om nästa och föregående länk också. Paginator- objektet kan hjälpa till med det, det är tillgängligt i kontextdata också.

app / templates / app / pokemon_detail.html

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

Som tidigare fylls sammanhanget med ditt modellobjekt under object och pokemon , den andra kommer från modellnamnet.

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

I det här utdraget byggs webbadressen för detaljvyn med den primära nyckeln. Det är också möjligt att använda en snigel som argument. Detta ger en finare url som är lättare att komma ihåg. Det kräver emellertid närvaron av ett fält som heter slug i din modell.

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

Om ett fält som heter slug inte finns, kan du använda slug_field inställningen i DetailView att peka på ett annat fält.

För pagination, använd en sida för att få parametrar eller lägg en sida direkt i url-adressen.

Form och objekt skapande

Att skriva en vy för att skapa objekt kan vara ganska tråkigt. Du måste visa ett formulär, du måste bekräfta det, du måste spara objektet eller returnera formuläret med ett fel. Om du inte använder en av de generiska redigeringsvyerna .

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 och UpdateView har två obligatoriska attribut, model och fields . Som standard använder båda ett mallnamn baserat på modellnamnet som är "fixat" av formen. Du kan bara ändra suffixet med attributet template_name_suffix. DeleteView visar ett bekräftelsemeddelande innan objektet tas bort.

Både UpdateView och DeleteView måste hämta på objekt. De använder samma metod som DetailView , extraherar variabeln från url och matchar objektfälten.

app / mallar / app / pokemon_form.html (extrakt)

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

form innehåller formuläret med alla fält som behövs. Här kommer det att visas med ett stycke för varje fält på grund av as_p .

app / mallar / app / pokemon_confirm_delete.html (extrakt)

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

csrf_token taggen krävs på grund av django-skydd mot förfalskning av begäran. Attributåtgärden lämnas tom eftersom webbadressen som visar formuläret är densamma som den som hanterar borttagningen / spara.

Två problem kvarstår med modellen, om de använder samma som med listan och exemplen på detaljer. Först skapar och uppdaterar klagomål om en saknad omdirigeringsadress. Det kan lösas genom att lägga till en get_absolute_url till pokemonmodellen. Den andra frågan är att raderingsbekräftelsen inte visar meningsfull information. För att lösa detta är den enklaste lösningen att lägga till en strängrepresentation.

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

Klassdekoratören kommer att se till att allt fungerar smidigt under python 2.

Minimalt exempel

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

Läs mer om Django-dokumentation »

Django klassbaserade vyer: exempel på CreateView

Med klassbaserade generiska vyer är det mycket enkelt och enkelt att skapa CRUD-vyer från våra modeller. Ofta är den inbyggda Django-admin inte tillräckligt eller föredras och vi måste rulla våra egna CRUD-vyer. CBV: er kan vara mycket praktiska i sådana fall.

CreateView behöver CreateView saker - en modell, fälten som ska användas och framgångsadressen.

Exempel:

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

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

När skapandet har lyckats omdirigeras användaren till success_url . Vi kan också definiera en metod get_success_url istället och använda reverse eller reverse_lazy att få framgångsadressen.

Nu måste vi skapa en mall för den här vyn. Mallen ska namnges i formatet <app name>/<model name>_form.html . Modellnamnet måste vara i nedre lock. Till exempel, om mitt appnamn är dashboard måste jag skapa en mall med dashboard/campaign_form.html för ovanstående dashboard/campaign_form.html .

I mallen, en form skulle variabel innehåller formuläret. Här är ett exempelkod för mallen:

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

Nu är det dags att lägga till vyn i våra url-mönster.

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

Om vi besöker URL: n bör vi se ett formulär med de fält vi valde. När vi skickar in kommer den att försöka skapa en ny instans av modellen med data och spara den. Vid framgång kommer användaren att omdirigeras till framgångsadressen. Vid fel kommer formuläret att visas igen med felmeddelandena.

En vy, flera formulär

Här är ett snabbt exempel på att använda flera former i en Django-vy.

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow