Zoeken…


Opmerkingen

Bij het gebruik van CBV moeten we vaak precies weten welke methoden we voor elke generieke klasse kunnen overschrijven. Deze pagina van de django-documentatie geeft een overzicht van alle generieke klassen met al hun methoden afgeplat en de klassenattributen die we kunnen gebruiken.

Bovendien biedt de Classy Class Based View- website dezelfde informatie met een mooie interactieve interface.

Op klassen gebaseerde weergaven

Op klassen gebaseerde weergaven laten u zich concentreren op wat uw weergaven speciaal maakt.

Een statische pagina over heeft misschien niets bijzonders, behalve de gebruikte sjabloon. Gebruik een TemplateView ! Het enige wat u hoeft te doen is een sjabloonnaam instellen. Klus geklaard. De volgende.

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

Merk op dat we de AboutView niet rechtstreeks AboutView in de url. Dat komt omdat een opvraagbaar wordt verwacht en dat is precies wat as_view() retourneert.

Context gegevens

Soms heeft uw sjabloon wat meer informatie nodig. We willen bijvoorbeeld dat de gebruiker in de koptekst van de pagina staat, met een link naar zijn profiel naast de uitloglink. Gebruik in deze gevallen de 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

U moet de methode get_context_data aanroepen in de superklasse en deze retourneert de standaardcontextinstantie. Elk item dat u aan dit woordenboek toevoegt, is beschikbaar voor de sjabloon.

book.html

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

Lijst- en detailweergave

Sjabloonweergaven zijn prima voor statische pagina's en u kunt ze voor alles gebruiken met get_context_data maar het zou nauwelijks beter zijn dan de functie als weergaven te gebruiken.

Ga naar ListView en 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

Dat is alles wat u nodig hebt om een weergave te genereren met al uw objecten van modellen en weergaven van een enkelvoudig item. De lijst is zelfs gepagineerd. U kunt template_name als u iets specifieks wilt. Standaard wordt deze gegenereerd op basis van de modelnaam.

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>

De context wordt gevuld met de lijst met objecten onder twee naam, object_list en een tweede build van de modelnaam, hier pokemon_list . Als u de lijst hebt gepagineerd, moet u ook zorgen voor de volgende en vorige link. Het Paginator- object kan daarbij helpen, het is ook beschikbaar in de contextgegevens.

app / templates / app / pokemon_detail.html

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

Zoals eerder wordt de context gevuld met uw modelobject onder de naam object en pokemon , de tweede wordt afgeleid van de modelnaam.

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 dit fragment wordt de url voor de detailweergave opgebouwd met de primaire sleutel. Het is ook mogelijk om een slak als argument te gebruiken. Dit geeft een mooiere url die gemakkelijker te onthouden is. Het vereist echter de aanwezigheid van een veld met de naam slug in uw model.

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

Als een veld genaamd slug niet aanwezig is, kunt u het gebruik slug_field instelling in DetailView te wijzen op een ander veld.

Gebruik voor paginering een parameter voor het ophalen van pagina's of plaats een pagina rechtstreeks in de URL.

Vorm- en objectcreatie

Het schrijven van een weergave om een object te maken, kan behoorlijk saai zijn. U moet een formulier weergeven, u moet het valideren, u moet het item opslaan of het formulier met een fout retourneren. Tenzij u een van de generieke bewerkingsweergaven gebruikt .

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 en UpdateView hebben twee vereiste attributen, model en fields . Beide gebruiken standaard een sjabloonnaam op basis van de modelnaam met '_form'. U kunt alleen het achtervoegsel wijzigen met het kenmerk template_name_suffix. De DeleteView toont een bevestigingsbericht voordat het object wordt verwijderd.

Zowel UpdateView als DeleteView moeten op object worden DeleteView . Ze gebruiken dezelfde methode als DetailView , waarbij ze variabele uit de URL extraheren en overeenkomen met de objectvelden.

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

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

form bevat het formulier met alle benodigde velden. Hier wordt het weergegeven met een alinea voor elk veld vanwege as_p .

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

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

De csrf_token tag is vereist vanwege django-bescherming tegen vervalsing van aanvragen. De attribuutactie blijft leeg omdat de url die het formulier weergeeft hetzelfde is als degene die de verwijdering / opslag uitvoert.

Er blijven twee problemen met het model bestaan, als hetzelfde wordt gebruikt als met de lijst en het voorbeeld. Eerst maken en bijwerken zal klagen over een ontbrekende omleidings-URL. Dat kan worden opgelost door een get_absolute_url te voegen aan het pokemon-model. Tweede probleem is de verwijderingbevestiging die geen betekenisvolle informatie weergeeft. Om dit op te lossen, is de eenvoudigste oplossing een stringvoorstelling toe te voegen.

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

De klassedecorateur zorgt ervoor dat alles soepel werkt onder python 2.

Minimaal voorbeeld

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

Meer informatie over Django-documentatie »

Op Django-klasse gebaseerde weergaven: voorbeeld van CreateView

Met de op klassen gebaseerde generieke weergaven is het heel eenvoudig en gemakkelijk om de CRUD-weergaven op basis van onze modellen te maken. Vaak is de ingebouwde Django-beheerder niet genoeg of niet de voorkeur en moeten we onze eigen CRUD-weergaven maken. De CBV's kunnen in dergelijke gevallen erg handig zijn.

De klasse CreateView heeft 3 dingen nodig - een model, de te gebruiken velden en de succes-URL.

Voorbeeld:

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

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

Zodra het creëren is geslaagd, wordt de gebruiker omgeleid naar success_url . We kunnen in plaats daarvan ook een methode get_success_url definiëren en reverse of reverse_lazy gebruiken om de succes-URL te krijgen.

Nu moeten we een sjabloon maken voor deze weergave. De sjabloon moet een naam hebben in het formaat <app name>/<model name>_form.html . De modelnaam moet in kleine letters zijn. Als mijn app-naam bijvoorbeeld dashboard , moet ik voor de bovenstaande weergave maken een sjabloon met de naam dashboard/campaign_form.html .

In de sjabloon zou een form het formulier bevatten. Hier is een voorbeeldcode voor de sjabloon:

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

Nu is het tijd om de weergave toe te voegen aan onze URL-patronen.

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

Als we de URL bezoeken, zien we een formulier met de velden die we hebben gekozen. Wanneer we indienen, probeert het een nieuw exemplaar van het model met de gegevens te maken en op te slaan. Bij succes wordt de gebruiker omgeleid naar de succes-URL. Bij fouten wordt het formulier opnieuw weergegeven met de foutmeldingen.

Eén weergave, meerdere formulieren

Hier is een snel voorbeeld van het gebruik van meerdere formulieren in één Django-weergave.

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow