Tutoriel Python Django (5)

C'est un matériau pour les sessions d'étude Cette fois, je vais expliquer Form un peu en marge du tutoriel original. Avant d'entrer dans le formulaire, je vais vous présenter un peu la mise à jour de django et de l'espace de noms d'url.

Tutoriel Tutoriel Tutoriel 1 Tutoriel 2 Tutoriel 3 Tutoriel 4

Autres tutoriels

Source (github)

Aussi, jusqu'à la dernière fois, j'ai expliqué django1.8, mais depuis que django1.9 est sorti alors que je sautais les mises à jour. Dans les tutoriels suivants, nous expliquerons django 1.9. Même si vous changez la version de django de 1.8 à 1.9, il n'y a pas de différence particulière dans le contenu des tutoriels 1 à 4.

Migration vers django 1.9 et introduction de requirements.txt

Source → ʻee195d1`

mise à jour de Django

Vous pouvez mettre à jour vers la dernière version de django (1.9.2 au 20 février 2016) en tapant la commande suivante sur la ligne de commande. Si vous utilisez un environnement virtuel, n'oubliez pas d'activer l'environnement virtuel avec workon. (tutorial)$ pip install --upgrade django

(tutorial)$ pip install --upgrade django
Collecting django
  Using cached Django-1.9.2-py2.py3-none-any.whl
Installing collected packages: django
  Found existing installation: Django 1.8.6
    Uninstalling Django-1.8.6:
      Successfully uninstalled Django-1.8.6
Successfully installed django-1.9.2

S'il se termine normalement, il désinstallera le django déjà installé (1.8.6 dans ce cas) comme décrit ci-dessus, et installera le dernier django.

requirements.txt Dans ce didacticiel, django est la seule bibliothèque externe utilisée jusqu'à présent, mais le nombre de bibliothèques associées utilisées dans le futur augmentera régulièrement. Quelle bibliothèque utilisez-vous à ce moment-là? , La version de la bibliothèque est-elle la même? Il est difficile de vérifier à chaque fois. Heureusement, python a un système de gestion de paquets appelé «pip» et un environnement virtuel appelé «virtualenv». Vous ne souffrirez pas souvent de ce problème.

Pour obtenir une liste des bibliothèques utilisées dans l'environnement actuel, tapez la commande suivante dans le shell.

(tutorial)$ pip freeze
Django==1.9.2
wheel==0.24.0

Par convention en python, ce contenu est généré en tant que requirements.txt. Une autre personne peut installer les bibliothèques requises en important ce fichier. Comme vous pouvez le voir, le contenu de sortie a également un numéro de version tel que 1.9.2, il n'y a donc pas lieu de s'inquiéter des dysfonctionnements dus aux différentes versions.

J'avais l'intention de le mettre dans le tutoriel, mais je ne l'ai pas créé, donc je l'ai ajouté avec commit: ʻee195d1`.

Sortie de la bibliothèque que vous utilisez (création de requirements.txt)

(tutorial)$ pip freeze > requirements.txt

Redirigez simplement le contenu de pip freeze. Dans le cas de django, il est recommandé de le mettre dans la même hiérarchie que manage.py.

Importer la bibliothèque

Utilisez la commande pip install -r pour importer. Après avoir confirmé qu'il est workon dans l'environnement que vous souhaitez importer, après -r Décrivez le chemin vers le fichier que vous souhaitez importer (requirements.txt).

(tutorial)$ pip install -r requirements.txt

Si vous avez déjà installé une bibliothèque et souhaitez mettre à jour sa version (tutorial)$ pip install -U -r requirements.txt Vous avez besoin de l'option -U comme>. Cependant, quand je l'ai essayé à portée de main, il semble que si la version de pip est 8.0.2, elle sera mise à jour sans l'ajouter.

Ajouter un espace de noms à l'URL

Source → bba5e4f

Dans le didacticiel 3, j'ai ignoré l'explication de la conversion de l'espace de noms d'URL. Compte tenu de l'avenir, il est pratique de les séparer, alors définissez l'espace de noms dans l'url du sondage. Pour l'ajouter, ajoutez simplement namespace à l'argument de la fonction ʻinclude`.

tutorial/urls.py


urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^polls/', include('polls.urls')),
]

↓ Ajoutez namespace à l'argument include des sondages

tutorial/urls.py


urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^polls/', include('polls.urls', namespace='polls')),
]

Veillez à ne pas confondre la position de la parenthèse fermante avec un argument de la fonction url

Si vous définissez l'espace de noms, vous pouvez extraire l'URL sous la forme de namespace: hoge. L'espace de noms peut également être écrit dans une hiérarchie plus élevée, telle que ʻapi: polls: create. J'ai ajouté le préfixe poll_ au nom de la destination d'inclusion polls / urls.py`, Si vous utilisez un espace de noms, il ne sera pas nécessaire, supprimez-le.

polls/urls.py


urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'(?P<pk>\d+)/$', views.detail, name='poll_detail'),
    url(r'(?P<pk>\d+)/vote$', views.vote, name='poll_vote'),
    url(r'(?P<pk>\d+)/results$', views.results, name='poll_results'),
]

↓ Puisque l'espace de noms est coupé, le préfixe nommé poll_ devient inutile.

polls/urls.py


urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'(?P<pk>\d+)/$', views.detail, name='detail'),
    url(r'(?P<pk>\d+)/vote$', views.vote, name='vote'),
    url(r'(?P<pk>\d+)/results$', views.results, name='results'),
]

Dans django 1.9, au lieu d'écrire le nom de l'espace de noms dans l'argument include dans tutorial / urls.py Il peut également être défini en écrivant ʻapp_name = 'polls'danspolls / urls.py`. https://docs.djangoproject.com/en/1.9/releases/1.9/#passing-a-3-tuple-or-an-app-name-to-include

Avec ce changement, l'URL est maintenant extraite du nom vers polls: detail au lieu de poll_detail. Veuillez vérifier la différence de source pour la pièce corrigée.

En coupant l'espace de noms, l'application polls sera plus séparée du projet tutorial et sera plus facile à utiliser dans d'autres projets. Avec la méthode précédente, si une autre application du même projet donne un nom tel que poll_detail à l'URL, une erreur se produit. Vous devez faire attention aux noms d'URL de toutes les applications gérées par le projet. D'un autre côté, utilisez l'espace de noms pour éviter les conflits de namespace dans root urls.py ( tutorial / urls.py). Il faut juste faire attention.

Qu'est-ce que la forme

Maintenant, entrons enfin dans l'histoire de Form. Le formulaire est utilisé pour transmettre des données dans un certain format du client au serveur, comme le signifie la traduction anglaise de «formulaire, formulaire de demande». Dans le didacticiel 4, le formulaire a été écrit directement dans le modèle et le traitement après réception a été écrit du côté de la vue. Cependant, le modèle et la vue correspondent à la vue et au contrôleur dans le modèle MVC, et il n'est pas bon que la logique soit incluse ici. Aussi, dans le format actuel, l'affichage du bouton radio est décrit dans le modèle, et sa validation (détermination de l'exactitude des données sélectionnées), En outre, le traitement (traitement de vote) utilisant la valeur d'entrée est décrit dans la vue. Cependant, parce que les éléments d'entrée, leur validation et leur traitement à l'aide des données sont étroitement liés. Je veux les gérer ensemble. La classe Form est préparée dans django, et l'entrée générale (texte, liste de sélection, bouton radio, etc.) et Nous fournissons le validateur (contrôle d'entrée).

La classe Form facilite l'écriture de tests pour Honke Tutorial 5. Vous pouvez facilement augmenter le nombre d'éléments d'entrée, et il sera facile de les réutiliser ailleurs. De plus, en établissant un lien avec la vue générale basée sur les classes, la description de la vue peut être encore réduite et rendue plus facile à comprendre.

Classe de formulaire

Sortie de champ de texte

Source → 34698a1

Tout d'abord, essayons de créer un formulaire. Créez un fichier appelé forms.py dans le dossier de l'application et définissez-y la classe Form. Pour la classe Form, définissez la classe de champ en tant que membre. Veuillez vous référer au document officiel pour la classe de champ qui peut être définie. https://docs.djangoproject.com/en/1.9/ref/forms/fields/

Pour le moment, définissons CharField, qui est un champ de saisie de caractères. CharField doit spécifier le nombre maximum de caractères (max_length) comme argument requis, donc définissez 100 caractères pour le moment.

polls/forms.py


from django import forms


class MyForm(forms.Form):
    text = forms.CharField(max_length=100)

Vérifions la sortie pour voir ce qui se passe lorsque nous écrivons ceci. Démarrez le shell python avec ./manage.py shell, créez une instance de la classe Form créée précédemment et créez-la. Imprimons-le.

$ ./manage.py shell
(InteractiveConsole)
>>> from polls.forms import MyForm
>>> f = MyForm()
>>> print(f)
<tr><th><label for="id_text">Text:</label></th><td><input id="id_text" maxlength="100" name="text" type="text" /></td></tr>

Vous pouvez voir que la balise d'entrée de type texte est sortie en tant que sortie. Étant donné que le nom du champ est défini sur «texte», vous pouvez également confirmer que la chaîne de caractères «Texte» apparaît comme étiquette.

Sortie vers modèle, confirmation avec navigateur

Source → 34f4914

Ensuite, rendons la classe Form créée au format html. Tout d'abord, écrivez la création de formulaire et passez au modèle dans views.py.

polls/views.py


from .forms import MyForm


def form_test(request):
    form = MyForm()
    return render(request, 'polls/form.html', {
        'form': form,
    })

Ensuite, préparons un modèle. Puisque nous avons spécifié le chemin du modèle polls / form.html, l'emplacement du fichier est Il s'agit de polls / templates / polls / form.html.

polls/templates/polls/form.html


<html>
  <body>
    <form>
      {{ form }}
    </form>
  </body>
</html>

Vous devriez maintenant voir la chaîne suivante confirmée dans le shell dans {{form}}. <tr><th><label for="id_text">Text:</label></th><td><input id="id_text" maxlength="100" name="text" type="text" /></td></tr>

Enfin, connectez la fonction form_test et l'url. Ajoutons l'URL à polls / urls.py.

polls/urls.py


urlpatterns = [
...
    url(r'^form$', views.form_test),
...
]

Après avoir écrit jusqu'à présent, démarrez le serveur de test avec ./manage.py runserver et vérifiez-le avec un navigateur. url est http: // localhost: 8000 / polls / form.

Kobito.HyYPSO.png écran

C'est une scène meurtrière, mais pour le moment, vous pouvez voir qu'il y a une boîte pour l'entrée.

Kobito.JxJa67.png source html

La source html ressemble à ceci. Comme prévu, la partie {{form}} a été remplacée.

Processus de transmission POST

Source → 06c8422

Eh bien, la zone de saisie a été créée, mais il n'y a pas encore de processus de réception côté serveur. Lors de l'envoi de données au serveur avec html, décrivez ** où ** ** comment ** les données sont envoyées dans la balise <form>. Écrivez respectivement les attributs «action» et «method». De plus, pour envoyer, vous devez placer le bouton soumettre dans la balise <form>. Si vous souhaitez recevoir dans la même vue, vous n'avez pas besoin de spécifier «action». Cette fois, je ne l'écris qu'en caractères vides.

Veuillez noter que csrf_token est requis lors de l'envoi de données par POST.

Explication de csrf → [Tout le monde aime wikipedia](https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3% 82% A4% E3% 83% 88% E3% 83% AA% E3% 82% AF% E3% 82% A8% E3% 82% B9% E3% 83% 88% E3% 83% 95% E3% 82% A9% E3% 83% BC% E3% 82% B8% E3% 82% A7% E3% 83% AA)

Puisque la communication POST est une transmission de données html au serveur (= changement des informations du serveur) La manière dont elle a été saisie est importante. Dans django, en ajoutant la balise csrf_token, vous pouvez garantir que les données ont été saisies sur la page que vous avez préparée.

Le code HTML modifié est le suivant.

polls/templates/polls/form.html


<html>
  <body>
    <form action="" method="POST">
      {% csrf_token %}
      {{ form }}
      <input type="submit" value="Envoyer"/>
    </form>
  </body>
</html>

Kobito.1nDDdU.png Confirmez que le bouton est affiché dans le navigateur

Même si vous appuyez sur le bouton, rien ne se passe car rien n'est écrit après cela, Si vous regardez le journal sur l'écran où runsever est exécuté, vous pouvez confirmer que la communication POST est en cours.

(tutorial)$ ./manage.py runserver 127.0.0.1:13000
Performing system checks...

System check identified no issues (0 silenced).
February 21, 2016 - 16:56:38
Django version 1.9.2, using settings 'tutorial.settings'
Starting development server at http://127.0.0.1:13000/
Quit the server with CONTROL-C.

[21/Feb/2016 17:34:28] "GET /polls/form HTTP/1.1" 200 343    #← Affichage de l'écran
[21/Feb/2016 17:34:30] "POST /polls/form HTTP/1.1" 200 343   #← Cliquez sur le bouton «Envoyer»

Au fait, si vous oubliez d'écrire la balise {% csrf_token%} en html, ce sera comme ça.

Kobito.Ffr1Uf.png

Ce processus de vérification est effectué par MIDDLEWARE, et vous pouvez voir qu'il est défini par défaut en regardant settings.py.

tutorial/settings.py


MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',  #←←←←←←←← Traitement des chèques CSRF
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)

Traitement de la réception des données

Source → 8ea545ce

Les données POST reçues sont stockées dans la classe de requête avec le nom «POST». Ces données sont transmises à la classe Form, la validité des données est vérifiée et, si elles sont correctes, quelque chose est fait en utilisant ces données.

La vue modifiée ressemble à ceci.

polls/views.py


def form_test(request):
    if request.method == "POST":
        form = MyForm(data=request.POST)  #← Passer les données POST reçues
        if form.is_valid():  #← Confirmation de la validité des données reçues
            pass  #← Traitement lorsque des données correctes sont reçues
    else:  #← la méthode est'POST'n'est pas=Traitement lorsque la première page est affichée
        form = MyForm()
    return render(request, 'polls/form.html', {
        'form': form,
    })

Après avoir reçu les données correctes, les données sont enregistrées dans la base de données, etc. et un traitement tel que la redirection vers une autre page est effectué. Je n'ai rien fait cette fois. Vérifions le fonctionnement du navigateur dans cet état. Vous devriez voir un message d'erreur affiché lorsque vous appuyez sur le bouton Soumettre sans rien entrer dans Texte.

Kobito.Bgm3aT.png

Personnalisation du champ

Source → 5637b54

Vous pouvez modifier le comportement et la sortie d'un champ en passant un argument lors de sa création. Par exemple, passer «required = False» n'entraînera pas d'erreur même s'il n'y a pas de valeur d'entrée dans ce champ. Vous pouvez également changer le caractère de «Texte» en ajoutant l'argument «étiquette». Reportez-vous à ce qui suit pour les arguments qui peuvent être spécifiés. https://docs.djangoproject.com/en/1.9/ref/forms/fields/#core-field-arguments

Cette fois, définissons le "requis" et le "libellé" expliqués plus tôt.

polls/forms.py


class MyForm(forms.Form):
    text = forms.CharField(max_length=100, required=False, label='texte')

Kobito.WXYnel.png

Texte est maintenant Texte. De plus, je pense que vous pouvez confirmer que le message d'erreur a disparu même si vous avez appuyé sur envoyer sans rien entrer.

Formulaire de vote

Créer un formulaire de vote

Source → 9077adee

Réécrivons le formulaire de vote créé dans le didacticiel 4 à l'aide de la classe Form. L'entrée requise est un bouton radio permettant de sélectionner la liste de choix associée au modèle «question». ModelChoiceField peut être utilisé pour sélectionner un modèle. Ce champ nécessite un jeu de requête pour sélectionner le modèle, mais lors de la définition du champ, pour lequel question Puisqu'il n'est pas certain qu'il s'agisse d'un formulaire, nous remplacerons la méthode __init__ et la recevrons comme argument.

polls/forms.py


class VoteForm(forms.Form):
    choice = forms.ModelChoiceField(
        queryset=None,
        label='Choix',
        widget=forms.RadioSelect(),
        empty_label=None,
        error_messages={
            'required': "You didn't select a choice.",
            'invalid_choice': "invalid choice.",
        },

    )

    def __init__(self, question, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['choice'].queryset = question.choice_set.all()

Puisque le widget par défaut de ModelChoiceField est une liste de sélection, spécifiez RadioSelect pour le widget. Réglez le jeu de requêtes sur "Aucun" pour le moment, et écrasez-le avec l'argument dans "init". En définissant error_messages, vous pouvez spécifier des messages d'erreur lorsque diverses valeurs invalides sont entrées. Si non spécifié ici (obligatoire) et si une valeur non sélectionnée est saisie (invalid_choice) Un message d'erreur est défini.

Ensuite, sortons le formulaire créé en réécrivant views.py et les modèles.

polls/views.py


from .forms import VoteForm


def detail(request, pk):
    obj = get_object_or_404(Question, pk=pk)
    form = VoteForm(question=obj)
    return render(request, 'polls/detail.html', {
        'form': form,
        'question': obj,
    })

polls/templates/polls/detail.html


<h1>{{ question.question_text }}</h1>

<form action="{% url 'polls:vote' question.id %}" method="post">
    {% csrf_token %}
    {{ form }}
    <input type="submit" value="Vote" />
</form>

Kobito.5NwxDg.png Vérifier avec le navigateur

Le choix est «Objet de choix». Comme je l'ai mentionné un peu dans le didacticiel 2, la représentation sous forme de chaîne d'une instance ressemble par défaut à "ModelName object". Ouvrez models.py et remplacez la méthode __str__.

polls/models.py


class Choice(models.Model):
...
    def __str__(self):
        return self.choice_text

Kobito.cya0WW.png

Cela a bien changé.

D'ailleurs, contrairement au premier écran, il y a une tache noire supplémentaire devant chaque option, En effet, par défaut, chaque option est séparée par une balise «

  • ». Il est préférable d'éviter l'apparition de points noirs en css, Si vous voulez vraiment changer le html, vous pouvez réécrire le inner_html du moteur de rendu contenu par le widget.

  • polls/forms.py

    
    class VoteForm(forms.Form):
        def __init__(self, question, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.fields['choice'].queryset = question.choice_set.all()
            self.fields['choice'].widget.renderer.inner_html = '{choice_value}{sub_widgets}<br>'
    

    Kobito.j0CZTQ.png

    Description du processus de réception

    Source → 56f2b498

    Dans le Tutoriel 4, nous avons fourni une fonction pour recevoir des votes appelée «vote», mais elle n'a pas besoin d'être séparée. Décrivons le traitement des branches lorsque POST est terminé, comme lors de l'écriture avec form_test.

    polls/views.py

    
    def detail(request, pk):
        obj = get_object_or_404(Question, pk=pk)
        if request.method == "POST":
            form = VoteForm(question=obj, data=request.POST)
            if form.is_valid():
                # TODO:Processus de vote
                return redirect('polls:results', pk)
        else:
            form = VoteForm(question=obj)
        return render(request, 'polls/detail.html', {
            'form': form,
            'question': obj,
        })
    

    N'oubliez pas de corriger le côté html pour qu'il saute aux détails au lieu de voter.

    polls/templates/polls/detail.html

    
    <h1>{{ question.question_text }}</h1>
    
    <form action="" method="post">
      {% csrf_token %}
      {{ form }}
      <input type="submit" value="Vote" />
    </form>
    

    Effacer en action. Au fait, ʻerror_message` est également supprimé car la classe Form émet automatiquement.

    Description du post-traitement

    Source → 38eb2ec47

    C'est finalement le dernier travail. Déplaçons le processus de vote (le processus d'ajout de +1 aux votes du choix sélectionné et d'enregistrement) qui a été fait dans views.vote vers la classe Form.

    Ce que tu veux faire

    polls/views.py

    
    def vote(request, pk):
        question = get_object_or_404(Question, pk=pk)
        try:
            selected_choice = question.choice_set.get(pk=request.POST['choice'])
        except (KeyError, Choice.DoesNotExist):
            return render(request, 'polls/detail.html', {
                'question': question,
                'error_message': "You didn't select a choice.",
            })
        else:
            selected_choice.votes += 1
            selected_choice.save()
            return redirect('polls:results', pk)
    

    Alors, écrivez un processus pour incrémenter les votes de l'instance Choice sélectionnée dans la classe Form. Lorsque la classe Form exécute ʻis_valid () , les données obtenues en convertissant la valeur d'entrée dans un format approprié seront incluses dans cleaning_data. C'est un peu déroutant, mais sélectionnez-le dans html avec le bouton radio et sélectionnez-le. Les données transmises au serveur sont une représentation de caractères pk de l'instance de Choice, telle que "" 2 "ou" 3 "". Lorsque vous exécutez ʻis_valid () , il sera converti en une instance de ** Choice et placé dans ** dans cleaning_data.

    clean_data est au format dictionnaire avec chaque nom de champ comme clé, donc pour prendre une instance de choix Écrivez comme self.cleaned_data ['choice']. Sur la base de ce qui précède, si vous écrivez une méthode vote qui incrémente les votes de l'instance Choice sélectionnée, ce sera comme suit.

    polls/forms.py

    
    class VoteForm(forms.Form):
    ...
        def vote(self):
            assert(self.is_valid())
            choice = self.cleaned_data['choice']
            choice.votes += 1
            choice.save()
    

    assert est écrit pour clarifier que is_valid () a été exécuté et que la valeur d'entrée doit être valide.

    Une fois la méthode de vote créée, appelez-la du côté de la vue.

    polls/views.py

    
    def detail(request, pk):
        obj = get_object_or_404(Question, pk=pk)
        if request.method == "POST":
            form = VoteForm(question=obj, data=request.POST)
            if form.is_valid():
                form.vote()  #←←←←←←←←←←←← Ajouter ceci
                return redirect('polls:results', pk)
        else:
            form = VoteForm(question=obj)
        return render(request, 'polls/detail.html', {
            'form': form,
            'question': obj,
        })
    

    Ceci termine le processus. Puisque views.vote n'est plus nécessaire, supprimons-le. N'oubliez pas de le supprimer également de urls.py.

    champ et widget

    Le champ correspond aux données conservées en interne. Par exemple, dans le cas de CharField, les données internes (nettoyées_données) sont de type texte. Si c'est ʻIntegerField, ce sera un type numérique, et s'il s'agit deModelChoiceField` comme cette fois, ce sera une instance du modèle sélectionné.

    D'autre part, le widget est une interface graphique qui spécifie le type de pièces à afficher dans le navigateur. Dans le cas de ModelChoiceField, il s'agit d'une liste de sélection par défaut, mais vous pouvez la changer en un bouton radio comme cette fois. Il est également possible de créer la zone de texte (bien que ce soit la pire en entrée) et de saisir directement le pk de Choice. Il existe également un widget qui vous permet de saisir la date et l'heure séparément, tel que SplitDateTimeWidget.

    Il est facile de se tromper au début, mais décidons lequel changer en considérant si vous souhaitez modifier les données internes ou l'affichage sur le navigateur.

    Coopération avec la vue polyvalente basée sur les classes

    Réécriture de la fonction test_form

    Source → 7d19e395

    FormView est fourni comme une vue à usage général dans django. Tout d'abord, réécrivons form_test en utilisant cette classe.

    À propos, la fonction form_test à réécrire est divisée en plusieurs processus bien qu'elle soit courte.

    polls.py

    
    def form_test(request):
        if request.method == "POST":  #Traitement à la réception par la méthode POST
            form = MyForm(data=request.POST)  #Processus de création de formulaire (+Transmettez les données reçues à Form)
            if form.is_valid():
                pass #Traitement lorsque la valeur d'entrée du formulaire est correcte
        else:  #Traitement à la réception par la méthode GET
            form = MyForm()  #Processus de création de formulaire (pas de données)
        return render(request, 'polls/form.html', {  #Rendu du modèle
            'form': form,
        })
    

    Il a été foiré avec des commentaires, mais tout d'abord, il peut être divisé en gros selon qu'il a été appelé par GET ou POST. Dans le cas de GET, c'est le processus lorsque la page est affichée en premier, il n'y avait donc aucun argument lors de la création du formulaire. D'autre part, dans le cas de «POST», il existe un processus pour recevoir les données d'entrée après avoir affiché la page une fois. Data = request.POST est passé comme argument de Form. De plus, la validité de ces données est jugée (form.is_valid ()), et si elle est correcte, un traitement sera effectué. Dans la classe FormView fournie par django, chacun de ces processus est une méthode. Vous pouvez modifier le traitement de la pièce concernée en remplaçant une méthode spécifique.

    Voici une liste des méthodes à remplacer lors de la modification de l'opération à titre d'exemple.

    (Il existe d'autres méthodes dont dispose la vue de base (comme une méthode qui appelle get quand GET))

    Méthodes qui peuvent être remplacées dans FormView

    
        def get(self, request, *args, **kwargs):  #Appelé à l'accès avec la méthode GET
        def post(self, request, *args, **kwargs):  #Appelé à l'accès avec la méthode POST
        def put(self, *args, **kwargs):  #Appelé à l'accès avec la méthode PUT
        def get_initial(self):  #Définir la valeur initiale de Form
        def get_prefix(self):  #Définir le préfixe du formulaire
        def get_form_class(self):  #Obtenez la classe Form à utiliser
        def get_form_kwargs(self):  #Récupère les arguments à transmettre à la classe Form
        def get_form(self, form_class=None):  #Obtenir une instance de la classe Form
        def get_success_url(self):  #URL à rediriger en cas de réussite
        def form_valid(self, form):  #Traitement normal
        def form_invalid(self, form):  #Que faire si les données sont incorrectes
        def get_context_data(self, **kwargs):  #Obtenez le contexte à transmettre au modèle
        def render_to_response(self, context, **response_kwargs):  #Créer une réponse
        def get_template_names(self):  #Obtenez le nom du modèle utilisé pour le rendu
    

    Il existe des méthodes appelées get_form_class et get_template_names pour spécifier la classe et le modèle Form à utiliser. Au lieu de remplacer cette méthode, il suffit de spécifier des valeurs de champ telles que form_class et template_name.

    Pour une page de formulaire simple, ce que vous spécifiez form_class: classe de formulaire à utiliser template_name: modèle utilisé pour le rendu success_url: URL vers laquelle passer en cas de succès Il n'y en a que trois.

    En plus de cela, vous voudrez faire quelque chose en cas de succès, vous écraserez donc form_valid.

    success_url est une spécification de chaîne de caractères. Si vous souhaitez utiliser le nom défini dans l'URL, utilisez le résolveur. Puisqu'il n'est pas possible de définir un champ avec resol_url lors de la définition d'une classe, utilisez reverse_lazy ou Il remplacera get_success_url.

    Le form_testh réécrit est le suivant.

    polls/views.py

    
    from django.views.generic import FormView
    from django.core.urlresolvers import reverse_lazy
    
    from .forms import MyForm
    ...
    class FormTest(FormView):
        form_class = MyForm
        template_name = 'polls/form.html'
        success_url = reverse_lazy('polls:index')
    
    form_test = FormTest.as_view()
    

    Supprimez le def form_test (request): que vous avez créé en premier car il est inutile. Conflit de noms et une erreur se produit.

    Lors de l'utilisation d'une vue basée sur les classes, comme la source ci-dessus Exécutez view name = class name.as_view () après avoir défini la classe.

    La fonction form_test que j'ai écrite au début contenait des instructions if pour le jugement de méthode et le jugement de données. Si vous utilisez FormView, le jugement sera poussé dans la classe Super, donc J'ai pu créer une vue sans instruction if (= logique).

    réécriture de fonction de détail

    Source → 1efe74c527

    Enfin, réécrivons la fonction de détail en une vue basée sur les classes. Tout d'abord, c'est assez compliqué pour ne pas convenir aux tutoriels. Il y a deux raisons

    1. Besoin d'une instance «Question» dans le modèle
    2. Nécessite une instance Question comme argument de la classe Form

    Si c'est seulement 1, l'histoire est facile, et il y a un DetailView pour afficher la page de détail d'une instance. L'affichage est terminé simplement en spécifiant le modèle et le modèle à utiliser dans cette classe, tout comme FormView. Bien sûr, vous pouvez changer le nom de l'argument reçu par \ # view (maintenant pk) et le nom de l'objet passé au modèle. \ # De plus, (* app_name * / * model_name * _detail.html) est utilisé par défaut même si vous ne spécifiez pas de modèle.

    De plus, pour le n ° 2, il est facile d'augmenter les arguments de la classe Form (il suffit de remplacer get_form_kwargs). Le fait que vous ayez besoin d'une instance "Question" complique l'histoire.

    Puisque SingleObjectMixin est préparé comme un mixin de la classe View qui acquiert une instance d'un certain modèle, Cette fois, nous utiliserons ce Mixin et FormView en combinaison.

    def detail(request, pk): obj = get_object_or_404(Question, pk=pk) if request.method == "POST": form = VoteForm(question=obj, data=request.POST) if form.is_valid(): form.vote() return redirect('polls:results', pk) else: form = VoteForm(question=obj) return render(request, 'polls/detail.html', { 'form': form, 'question': obj, })

     Détail avant réécriture
    
     ↓ Réécriture en utilisant la classe
    
    
    #### **`polls/views.py`**
    ```python
    
    from django.shortcuts import resolve_url
    from django.views.generic import FormView
    from django.views.generic.detail import SingleObjectMixin
    
    from .forms import VoteForm
    from .models import Question
    
    ...
    class Detail(SingleObjectMixin, FormView):
        model = Question
        form_class = VoteForm
        context_object_name = 'question'
        template_name = 'polls/detail.html'
    
        def get(self, request, *args, **kwargs):
            self.object = self.get_object()
            return super().get(request, *args, **kwargs)
    
        def post(self, request, *args, **kwargs):
            self.object = self.get_object()
            return super().post(request, *args, **kwargs)
    
        def get_form_kwargs(self):
            kwargs = super().get_form_kwargs()
            kwargs['question'] = self.object
            return kwargs
    
        def form_valid(self, form):
            form.vote()
            return super().form_valid(form)
    
        def get_success_url(self):
            return resolve_url('polls:results', self.kwargs['pk'])
    
    detail = Detail.as_view()
    

    Tout d'abord, vous avez besoin d'une instance de «Question» à la fois pour «GET» et «POST». self.object = self.get_object() J'essaye d'appeler. La classe de modèle à acquérir par cette méthode est spécifiée par model = Question. Puisque nous utilisons une instance Question avec le nom question dans le modèle, Le nom est spécifié par context_object_name = 'question'.

    Parce que cette instance est nécessaire comme argument de VoteForm Remplacer get_form_kwargs et ajouter l'argument question.

    Je veux voter si les données sont correctes, alors remplacez form_valid et J'essaye d'appeler «form.vote».

    Enfin, nous remplaçons get_success_url pour réécrire l'URL de destination. Puisque l'argument reçu par view est dans self.kwargs, le pk reçu de l'URL avec` self.kwargs ['pk'] ʻest passé à l'URL de résultat.

    "Ce n'est pas beaucoup plus simple que la première fonction detail, cela semble plus compliqué, mais est-ce normal d'en faire une classe?" Ceux qui pensent avoir oublié l'important. Les classes sont ** héritées et réutilisées **. Si vous créez une autre classe View avec cette classe en tant que super classe, tout comme vous avez créé la classe Detail en héritant de FormView Lors de l'écriture d'une vue qui effectue le même traitement, vous pouvez facilement créer une vue qui effectue la même opération simplement en réécrivant quatre champs tels que modèle. Si vous écrivez une vue en tant que fonction, veuillez saisir cette occasion pour envisager de passer à une vue basée sur les classes.


    Ensuite, nous utiliserons bootstrap pour nettoyer la conception.

    Vers le prochain tutoriel

    Autres tutoriels

    Recommended Posts

    Tutoriel Python Django (5)
    Tutoriel Python Django (2)
    Tutoriel Python Django (8)
    Tutoriel Python Django (6)
    Tutoriel Python Django (7)
    Tutoriel Python Django (1)
    Tutoriel du didacticiel Python Django
    Tutoriel Python Django (3)
    Tutoriel Python Django (4)
    Résumé du didacticiel Python Django
    Tutoriel Python
    Fiche technique du didacticiel Python Django
    Résumé du didacticiel Python
    mémo du didacticiel django
    Démarrer le didacticiel Django 1
    Tutoriel [Docker] (Python + php)
    Framework Web Django Python
    Didacticiel sur les associations polymorphes Django
    tutoriel simple django oscar
    Table de décalage Django Python
    Essayez Debian + Python 3.4 + django1.7 ……
    Mémo du didacticiel Python OpenCV
    [Tutoriel Python] Structure des données
    Note du didacticiel Django Girls
    Tutoriel Cloud Run (python)
    Python Django CSS reflété
    Faites Django avec CodeStar (Python3.6.8, Django2.2.9)
    Lancez-vous avec Django! ~ Tutoriel ⑤ ~
    Introduction à Python Django (2) Win
    [Tutoriel Python] Outil de structure de contrôle
    Python
    Faites Django avec CodeStar (Python3.8, Django2.1.15)
    Python3 + Django ~ Mac ~ avec Apache
    Création de liste de tâches [Python Django]
    Premiers pas avec Python Django (1)
    Lancez-vous avec Django! ~ Tutoriel ④ ~
    Django
    Premiers pas avec Python Django (4)
    Premiers pas avec Python Django (3)
    Lancez-vous avec Django! ~ Tutoriel ⑥ ~
    Installez Python 3.7 et Django 3.0 (CentOS)
    [Python] Tutoriel personnel sur l'arbre de décision
    Histoire addictive GAE + python + Django
    Introduction à Python Django (6)
    Premiers pas avec Python Django (5)
    Jusqu'à la sortie de Python [Django] de Web service [Tutorial Part 1]
    Analyse des ondes cérébrales avec Python: tutoriel Python MNE
    8 commandes fréquemment utilisées dans Python Django
    Python practice_Configuration de l'environnement virtuel ~ Installation de Django
    Créer une nouvelle application utiliser python, django
    python + django + scikit-learn + mecab (1) avec heroku
    python + django + scikit-learn + mecab (2) avec heroku
    Exécutez python3 Django1.9 avec mod_wsgi (déployer)
    Résumé du didacticiel Django Girls Première moitié
    Trébucher lors du didacticiel django 1.7
    Déployer le didacticiel Django sur IIS ①
    Installer le framework Python django à l'aide de pip
    Introduction à Python Django (2) Édition Mac
    [Tutoriel Python] Une introduction facile à Python
    Historique d'apprentissage pour participer au développement d'applications d'équipe avec Python ~ Tutoriel Django 5 ~