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>
        &ndash; {{ 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)


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow