Django
Viste basate sulla classe
Ricerca…
Osservazioni
Quando si usa CBV, spesso abbiamo bisogno di sapere esattamente quali metodi possiamo sovrascrivere per ogni classe generica. Questa pagina della documentazione di django elenca tutte le classi generiche con tutti i loro metodi appiattiti e gli attributi di classe che possiamo usare.
Inoltre, il sito Web Classy Class Based View fornisce le stesse informazioni con una bella interfaccia interattiva.
Viste basate sulla classe
Le visualizzazioni basate su classi ti consentono di concentrarti su ciò che rende le tue visualizzazioni speciali.
Una pagina statica sulla pagina potrebbe non avere nulla di speciale, tranne il modello usato. Usa un TemplateView ! Tutto quello che devi fare è impostare un nome per il modello. Lavoro fatto. Il prossimo.
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'),
]
Si noti come non usiamo direttamente AboutView
. Questo perché ci si aspetta un callable e questo è esattamente ciò che as_view()
restituisce.
Dati contestuali
A volte, il tuo modello ha bisogno di un po 'più di informazioni. Ad esempio, vorremmo avere l'utente nell'intestazione della pagina, con un link al suo profilo accanto al link di disconnessione. In questi casi, utilizzare il metodo 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
È necessario chiamare il metodo get_context_data sulla super classe e restituirà l'istanza di contesto predefinita. Qualsiasi elemento aggiunto a questo dizionario sarà disponibile per il modello.
book.html
<h3>Active publishers</h3>
<ul>
{% for publisher in publishers %}
<li>{{ publisher.name }}</li>
{% endfor %}
</ul>
Elenco e dettagli
Le viste del modello vanno bene per la pagina statica e potresti usarle per tutto con get_context_data
ma sarebbe a malapena migliore dell'uso della funzione come viste.
Inserisci ListView e 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
Questo è tutto ciò che serve per generare una vista che elenchi tutti gli oggetti di un modello e le viste di un oggetto singolare. L'elenco è persino impaginato. Puoi fornire template_name
se vuoi qualcosa di specifico. Per impostazione predefinita, viene generato dal nome del modello.
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>
– {{ pokemon.species }}
</ul>
Il contesto è popolato con l'elenco di oggetti sotto il nome due, object_list
e una seconda build dal nome del modello, qui pokemon_list
. Se hai impaginato la lista, devi occuparti anche del link precedente e successivo. L'oggetto Paginator può essere d'aiuto, è disponibile anche nei dati di contesto.
app / templates / app / pokemon_detail.html
<!DOCTYPE html>
<title>Pokemon {{ pokemon.name }}</title>
<h1>{{ pokemon.name }}</h1>
<h2>{{ pokemon.species }} </h2>
Come in precedenza, il contesto viene popolato con l'oggetto del modello sotto l' object
nome e il pokemon
, il secondo derivato dal nome del modello.
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 questo snippet, l'url per la vista dettagliata viene creato utilizzando la chiave primaria. È anche possibile usare una lumaca come argomento. Questo dà un URL più bello che è più facile da ricordare. Tuttavia richiede la presenza di un campo chiamato slug nel tuo modello.
url(r'^pokemon/(?P<slug>[A-Za-z0-9_-]+)/$', views.PokemonView.as_view(), name='pokemon'),
Se un campo chiamato slug
non è presente, è possibile utilizzare la slug_field
impostazione DetailView
per puntare a un campo diverso.
Per l'impaginazione, utilizza una pagina per ottenere parametri o inserire una pagina direttamente nell'URL.
Creazione di forme e oggetti
Scrivere una vista per creare oggetti può essere piuttosto noioso. Devi visualizzare un modulo, devi convalidarlo, devi salvare l'oggetto o restituire il modulo con un errore. A meno che non si usi una delle viste di modifica generiche .
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
e UpdateView
hanno due attributi, model
e fields
obbligatori. Per impostazione predefinita, entrambi utilizzano un nome di modello basato sul nome del modello con suffisso "_form". Puoi modificare solo il suffisso con l'attributo template_name_suffix. DeleteView mostra un messaggio di conferma prima di eliminare l'oggetto.
Sia UpdateView
che DeleteView
devono recuperare l'oggetto. Usano lo stesso metodo di DetailView
, estraendo la variabile dall'URL e facendo corrispondere i campi dell'oggetto.
app / templates / app / pokemon_form.html (estratto)
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
form
contiene il modulo con tutti i campi necessari. Qui, verrà visualizzato con un paragrafo per ogni campo a causa di as_p
.
app / templates / app / pokemon_confirm_delete.html (estratto)
<form action="" method="post">
{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
<input type="submit" value="Confirm" />
</form>
Il tag csrf_token
è richiesto a causa della protezione di django contro la falsificazione delle richieste. L'azione attributo è lasciata vuota poiché l'url che visualizza il modulo è uguale a quello che gestisce la cancellazione / salvataggio.
Rimangono due problemi con il modello, se si utilizza lo stesso esempio con l'elenco e l'esempio di dettaglio. In primo luogo, creare e aggiornare si lamenterà di un URL di reindirizzamento mancante. Questo può essere risolto aggiungendo un get_absolute_url
al modello pokemon. Il secondo problema è la conferma dell'eliminazione che non mostra informazioni significative. Per risolvere questo problema, la soluzione più semplice è aggiungere una rappresentazione di stringa.
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
Il decoratore di classe si assicurerà che tutto funzioni correttamente sotto python 2.
Esempio minimo
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()),
]
Ulteriori informazioni sulla documentazione di Django »
Viste basate sulla classe Django: esempio di CreateView
Con le viste generiche basate sulla classe, è molto semplice e facile creare le viste CRUD dai nostri modelli. Spesso, l'amministratore di Django integrato non è abbastanza o non è preferito e abbiamo bisogno di lanciare le nostre visualizzazioni CRUD. I CBV possono essere molto utili in questi casi.
La classe CreateView
bisogno di 3 cose: un modello, i campi da usare e l'url di successo.
Esempio:
from django.views.generic import CreateView
from .models import Campaign
class CampaignCreateView(CreateView):
model = Campaign
fields = ('title', 'description')
success_url = "/campaigns/list"
Una volta che il successo della creazione, l'utente viene reindirizzato a success_url
. Possiamo anche definire un metodo get_success_url
e utilizzare reverse
o reverse_lazy
per ottenere l'URL di successo.
Ora, dobbiamo creare un modello per questa vista. Il modello deve essere denominato nel formato <app name>/<model name>_form.html
. Il nome del modello deve essere in maiuscolo. Ad esempio, se il mio nome dell'app è dashboard
, per la vista create sopra devo creare un modello denominato dashboard/campaign_form.html
.
Nel modello, una variabile form
contiene il modulo. Ecco un codice di esempio per il modello:
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
Ora è il momento di aggiungere la vista ai nostri modelli di URL.
url('^campaign/new/$', CampaignCreateView.as_view(), name='campaign_new'),
Se visitiamo l'URL, dovremmo vedere un modulo con i campi che abbiamo scelto. Quando inviamo, cercherà di creare una nuova istanza del modello con i dati e salvarla. In caso di successo, l'utente verrà reindirizzato all'URL di successo. In caso di errori, il modulo verrà visualizzato di nuovo con i messaggi di errore.
Una vista, più moduli
Ecco un rapido esempio di utilizzo di più moduli in una vista 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)