Django
Vues basées sur la classe
Recherche…
Remarques
Lorsque vous utilisez CBV, nous avons souvent besoin de savoir exactement quelles méthodes nous pouvons écraser pour chaque classe générique. Cette page de la documentation de django répertorie toutes les classes génériques avec toutes leurs méthodes aplaties et les attributs de classe que nous pouvons utiliser.
De plus, le site Web Classy Class Based View fournit les mêmes informations avec une interface interactive agréable.
Vues basées sur la classe
Les vues en classe vous permettent de vous concentrer sur ce qui rend vos vues spéciales.
Une page statique à propos de la page peut n'avoir rien de spécial, à l'exception du modèle utilisé. Utilisez un TemplateView ! Tout ce que vous avez à faire est de définir un nom de modèle. Travail terminé. Prochain.
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'),
]
Remarquez comment nous n'utilisons pas directement AboutView
dans l'URL. C'est parce qu'un appelable est attendu et c'est exactement ce que as_view()
.
Données de contexte
Parfois, votre modèle nécessite un peu plus d'informations. Par exemple, nous aimerions que l'utilisateur figure dans l'en-tête de la page, avec un lien vers son profil à côté du lien de déconnexion. Dans ces cas, utilisez la méthode 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
Vous devez appeler la méthode get_context_data sur la super classe et elle renverra l'instance de contexte par défaut. Tout élément que vous ajoutez à ce dictionnaire sera disponible pour le modèle.
book.html
<h3>Active publishers</h3>
<ul>
{% for publisher in publishers %}
<li>{{ publisher.name }}</li>
{% endfor %}
</ul>
Vues de liste et de détails
Les vues de modèle conviennent bien à la page statique et vous pouvez les utiliser pour tout avec get_context_data
mais cela ne serait guère mieux que d'utiliser la fonction comme vue.
Entrez ListView et 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
C'est tout ce dont vous avez besoin pour générer une vue répertoriant tous vos objets d'un modèle et les vues d'un élément singulier. La liste est même paginée. Vous pouvez fournir template_name
si vous voulez quelque chose de spécifique. Par défaut, il est généré à partir du nom du modèle.
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>
Le contexte est rempli avec la liste des objets sous deux noms, object_list
et un deuxième build à partir du nom du modèle, ici pokemon_list
. Si vous avez paginé la liste, vous devez également vous occuper du lien suivant et précédent. L'objet Paginator peut vous aider, il est également disponible dans les données de contexte.
app / templates / app / pokemon_detail.html
<!DOCTYPE html>
<title>Pokemon {{ pokemon.name }}</title>
<h1>{{ pokemon.name }}</h1>
<h2>{{ pokemon.species }} </h2>
Comme précédemment, le contexte est rempli avec votre objet modèle sous l' object
name et pokemon
, le second étant dérivé du nom du modèle.
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'),
]
Dans cet extrait de code, l'URL de la vue de détail est générée à l'aide de la clé primaire. Il est également possible d'utiliser un slug comme argument. Cela donne une URL plus belle, plus facile à retenir. Cependant, il nécessite la présence d'un champ nommé slug dans votre modèle.
url(r'^pokemon/(?P<slug>[A-Za-z0-9_-]+)/$', views.PokemonView.as_view(), name='pokemon'),
Si un champ appelé slug
n'est pas présent, vous pouvez utiliser la slug_field
mise en DetailView
pour pointer vers un autre domaine.
Pour la pagination, utilisez une page get parameters ou placez une page directement dans l'URL.
Création de forme et d'objet
Ecrire une vue pour créer un objet peut être assez ennuyeux. Vous devez afficher un formulaire, vous devez le valider, vous devez enregistrer l'élément ou renvoyer le formulaire avec une erreur. Sauf si vous utilisez l'une des vues d'édition génériques .
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
et UpdateView
ont deux attributs requis, le model
et les fields
. Par défaut, les deux utilisent un nom de modèle basé sur le nom de modèle suffixé par «_form». Vous ne pouvez modifier que le suffixe avec l'attribut template_name_suffix. DeleteView affiche un message de confirmation avant de supprimer l'objet.
UpdateView
et DeleteView
doivent être DeleteView
sur l'objet. Ils utilisent la même méthode que DetailView
, en extrayant une variable de l'URL et en faisant correspondre les champs d'objet.
app / templates / app / pokemon_form.html (extrait)
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
form
contient le formulaire avec tous les champs nécessaires. Ici, il sera affiché avec un paragraphe pour chaque champ à cause de as_p
.
app / templates / app / pokemon_confirm_delete.html (extrait)
<form action="" method="post">
{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
<input type="submit" value="Confirm" />
</form>
La balise csrf_token
est requise en raison de la protection django contre la falsification de requêtes. L'action d'attribut est laissée vide car l'URL affichant le formulaire est la même que celle qui gère la suppression / sauvegarde.
Il reste deux problèmes avec le modèle, si vous utilisez la même chose que pour la liste et l'exemple de détail. Tout d'abord, créer et mettre à jour se plaindra d'une URL de redirection manquante. Cela peut être résolu en ajoutant un get_absolute_url
au modèle pokemon. Le deuxième problème est la confirmation de suppression qui n’affiche aucune information significative. Pour résoudre ce problème, la solution la plus simple consiste à ajouter une représentation sous forme de chaîne.
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
Le décorateur de classe s'assurera que tout fonctionne correctement sous Python 2.
Exemple minimal
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()),
]
En savoir plus sur la documentation de Django »
Vues basées sur la classe Django: exemple de CreateView
Avec les vues génériques basées sur les classes, il est très simple et facile de créer les vues CRUD à partir de nos modèles. Souvent, l'admin de Django intégré n'est pas suffisant ou pas préféré et nous devons déployer nos propres vues CRUD. Les CBV peuvent être très utiles dans de tels cas.
La classe CreateView
besoin de 3 choses: un modèle, les champs à utiliser et l'URL de réussite.
Exemple:
from django.views.generic import CreateView
from .models import Campaign
class CampaignCreateView(CreateView):
model = Campaign
fields = ('title', 'description')
success_url = "/campaigns/list"
Une fois la création réussie, l'utilisateur est redirigé vers success_url
. Nous pouvons également définir une méthode get_success_url
place et utiliser reverse
ou reverse_lazy
pour obtenir l'URL de succès.
Maintenant, nous devons créer un modèle pour cette vue. Le modèle doit être nommé au format <app name>/<model name>_form.html
. Le nom du modèle doit être en lettres majuscules. Par exemple, si le nom de mon application est dashboard
, pour la vue de création ci-dessus, je dois créer un modèle nommé dashboard/campaign_form.html
.
Dans le modèle, une variable de form
contiendrait le formulaire. Voici un exemple de code pour le modèle:
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
Maintenant il est temps d'ajouter la vue à nos modèles d'URL.
url('^campaign/new/$', CampaignCreateView.as_view(), name='campaign_new'),
Si nous visitons l'URL, nous devrions voir un formulaire avec les champs que nous avons choisis. Lorsque nous soumettons, il essaiera de créer une nouvelle instance du modèle avec les données et de l'enregistrer. En cas de succès, l'utilisateur sera redirigé vers l'URL de succès. En cas d'erreur, le formulaire sera à nouveau affiché avec les messages d'erreur.
Une vue, plusieurs formulaires
Voici un exemple rapide d'utilisation de plusieurs formulaires dans une vue 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)