Ceci est la suite de cet article. Une «unité de type projet» est un «projet» dans un outil de gestion de tâches, etc. Ici, puisque le théâtre est géré, la «performance» lui correspond.
---> Dépôt GitHub (Python 3.8.1, Django 3.0.3)
La dernière fois, nous avons créé des «performances» et des «utilisateurs de performance» et un accès contrôlé. Nous avons également permis aux «utilisateurs d'une performance» d'ajouter des données (acteurs) appartenant à cette performance.
Cette fois, j'aimerais réfléchir à l'interface pour ajouter et éditer les données appartenant à la performance.
Par exemple, si vous créez un champ ForeignKey
appelé" Casting "dans les données" Characters "et que vous vous référez à" Actors ", vous voulez pouvoir sélectionner uniquement les acteurs pour cette performance.
Cependant, juste en créant «Modèle» et «Vue» comme indiqué ci-dessous, tous les acteurs (y compris les acteurs appartenant à d'autres performances) peuvent être sélectionnés comme «casting».
models.py
from django.db import models
class Character(models.Model):
'''Personnage
'''
production = models.ForeignKey(Production, verbose_name='Performance',
on_delete=models.CASCADE)
name = models.CharField('Nom de rôle', max_length=50)
cast = models.ForeignKey(Actor, verbose_name='Fonderie',
on_delete=models.SET_NULL, blank=True, null=True)
views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from .models import Character
class ChrCreate(LoginRequiredMixin, CreateView):
'''Vue supplémentaire du personnage
'''
model = Character
fields = ('name', 'cast')
▲ Vous pouvez choisir les acteurs d'autres performances.
Pensez à ajouter un «caractère» à une «performance». «Personnages» a un champ appelé «Casting», et «fait référence aux« données d'acteur »appartenant à la performance».
L'illustration ci-dessus est "un exemple où les acteurs d'autres performances peuvent choisir", mais à part ce problème, l'interface utilisateur est correcte.
Étant donné que la requête envoyée depuis le navigateur Web peut avoir été falsifiée, non seulement les options de l'interface utilisateur mais aussi la «valeur acceptée» devraient être limitées à «seulement l'acteur de la performance».
Pensez au moment où vous souhaitez modifier les «caractères» ajoutés ultérieurement. Ce serait le Mokuami original si l'affiliation (performance) du personnage qui a choisi «l'acteur de la performance» pouvait être modifiée. Il semble bon de rendre impossible la modification de l'affiliation du «personnage» une fois créé.
Cette application utilise une vue basée sur les classes (CreateView
), de sorte que le formulaire est automatiquement généré et vous pouvez écrire le modèle comme suit:
modelname_form.html
<form method="post">
{% csrf_token %}
<table>
{{ form }}
</table>
{% if object %}
<input type="submit" value="mise à jour">
{% else %}
<input type="submit" value="ajouter à">
{% endif %}
</form>
L'interface utilisateur d'entrée pour chaque champ de l'objet est développée dans cette partie appelée {{form}}
, donc vous pouvez également la réécrire ici.
Dans ce cas, vous devez passer le choix «cast» en tant que «contexte» et également séparer la façon dont le formulaire est écrit dans le modèle pour chaque champ.
Ici, nous allons l'arrêter et modifier à l'avance le contenu du formulaire développé dans la partie {{form}}
.
Une façon de modifier le contenu d'un formulaire consiste à créer une sous-classe du formulaire, mais vous pouvez le modifier sans le faire. Ici, nous allons le modifier dans la méthode de la vue. Nous parlerons des formulaires de sous-classification plus tard.
Un formulaire est un type de contexte
passé d'une vue à un modèle, vous pouvez donc remplacerget_context_data () ʻet le modifier comme suit:
ProdBaseCreateView`, dont la vue hérite dans le code ci-dessous, est une classe abstraite qui reçoit l'ID de performance et contrôle l'accès (voir Article précédent pour plus de détails). S'il vous plaît voir. Vous n'avez pas à vous inquiéter trop maintenant).
rehearsal/views/views.py
class ChrCreate(ProdBaseCreateView):
'''Vue supplémentaire du personnage
'''
model = Character
fields = ('name', 'cast')
def get_context_data(self, **kwargs):
'''Modifier les paramètres passés au modèle
'''
context = super().get_context_data(**kwargs)
#Afficher uniquement les acteurs de la performance
actors = Actor.objects.filter(production=self.production)
#Créer un choix
choices = [('', '---------')]
choices.extend([(a.id, str(a)) for a in actors])
#Mettre en forme
context['form'].fields['cast'].choices = choices
return context
--context ['form']
vous permet de voir le formulaire que la vue essaie de transmettre au modèle.
--Si vous définissez choix
dans un champ du formulaire, il sera affiché comme un choix.
choix
est un tuple de" valeur "et" chaîne d'affichage ".cast
sur vide, de sorte que la valeur de la première option est vide.▲ Seuls les acteurs de la performance auxquels appartiennent les personnages étaient affichés.
Je vois des informations selon lesquelles la définition de «choix» dans un champ d'un formulaire repousse automatiquement les autres valeurs, mais lorsque je l'ai essayé, ce n'est pas le cas. Cela peut être dû au fait que le champ avec «choix» était «ForeignKey».
▲ Essayez de falsifier les options de votre navigateur.
▲ La valeur altérée a été ajoutée.
Vous pouvez remplacer les méthodes de la vue pour modifier les résultats de la validation. En fin de compte, il est plus propre de créer une sous-classe du formulaire, mais d'abord ne le faisons qu'avec la vue.
rehearsal/views/views.py
class ChrCreate(ProdBaseCreateView):
# (Omission)
def form_valid(self, form):
'''Une fois la validation réussie
'''
#La validation a échoué si le casting n'est pas l'acteur de la même performance
instance = form.save(commit=False)
if instance.cast.production != self.production:
return self.form_invalid(form)
return super().form_valid(form)
form_valid ()
est une méthode de traitement côté vue qui est appelée lorsque le formulaire passe la validation.
Vous pouvez empêcher la sauvegarde en appelant de force la méthode (form_invalid ()
) qui est appelée lorsque la validation n'est pas passée.
--form.save (commit = False)
obtient l'objet que le formulaire tente de sauvegarder. Si vous définissez commit = True
, il sera sauvegardé puis récupéré.
self.object
et form.instance
, mais je ne comprends pas vraiment la différence. Je serais reconnaissant à quiconque sachant cela de me le faire savoir.
--self.production
dans l'instruction ʻif est un attribut de la superclasse de la vue
ProdBaseCreateView`, qui a la "performance" à laquelle appartient l'objet que vous essayez de sauvegarder (voir [Pour plus d'informations]. Veuillez consulter l'article précédent](https://qiita.com/satamame/items/959e21ade18c48e1b4d6).Vous pouvez trouver désagréable d'appeler form_invalid ()
depuis form_valid ()
comme ci-dessus.
Si vous pensez à la signification de form_valid ()
comme "l'endroit où vous êtes appelé lorsque vous passez la validation et continuez le traitement", c'est parce qu'il y a un sentiment d'incongruité comme un acte de sur-redressement.
En conséquence, form_invalid ()
est appelé, et il semble qu'un tel retour chabudai soit autorisé.
Dans le pire des cas, vous pouvez autoriser form_valid ()
à appeler form_valid ()
ainsi, ce qui entraîne un appel circulaire.
Bien sûr, si vous décidez des règles telles que le rendre à sens unique, il n'y a aucun problème avec la méthode ci-dessus.
Si vous voulez sous-classer le formulaire, vous n'avez même pas besoin de remplacer le get_context_data ()
que vous avez fait dans "Modifier l'interface utilisateur".
Au lieu de cela, la vue remplace une méthode appelée get_form_kwargs ()
.
C'est une image qui personnalise le formulaire généré lui-même, au lieu de modifier le "formulaire à transmettre au modèle".
La valeur de retour qui peut être obtenue avec get_form_kwargs ()
est un dictionnaire d'arguments de mots clés passés au constructeur de formulaire.
Donc, si vous ajoutez une entrée à cela, vous pouvez l'utiliser du côté formulaire.
Voici un exemple de remplacement de get_form_kwargs ()
en supposant qu'une classe appelée ChrForm
est définie.
Si vous définissez form_class
dans la vue, ne définissez pas champs
(je pense que cela entraînerait une erreur).
rehearsal/views/views.py
from rehearsal.forms import ChrForm
class ChrCreate(ProdBaseCreateView):
'''Vue supplémentaire du personnage
'''
model = Character
form_class = ChrForm
def get_form_kwargs(self):
'''Modifier les informations transmises au formulaire
'''
kwargs = super().get_form_kwargs()
#Passer la production car il est utilisé pour la validation côté formulaire
kwargs['production'] = self.production
return kwargs
rehearsal/forms.py
from django import forms
from production.models import Production
from .models Character
class ChrForm(forms.ModelForm):
'''Formulaire d'ajout / mise à jour de personnage
'''
class Meta:
model = Character
fields = ('name', 'cast')
def __init__(self, *args, **kwargs):
#Extraire les paramètres ajoutés dans la vue
production = kwargs.pop('production')
super().__init__(*args, **kwargs)
#Le casting ne peut être sélectionné que par les acteurs de la même performance
queryset = Actor.objects.filter(production=production)
self.fields['cast'].queryset = queryset
Vous définissez «queryset» au lieu de «choix» dans le champ «cast». Cela vous permettra de générer et de valider des choix en fonction de l'ensemble de requêtes que vous avez défini.
Si vous créez ce formulaire, vous pouvez l'utiliser non seulement pour la vue supplémentaire, mais également pour la vue de mise à jour.
Maintenant, modifions les options que nous avons faites dans "Validation".
Interdisez les modifications de production
dans ces vues d'ajout / mise à jour afin que vous ne puissiez pas changer la" performance "des" personnages "ou des" acteurs ".
Si vous créez un formulaire avec model
normalement dans Django, tous les champs seront modifiables, vous devez donc spécifier les champs modifiables.
--Si vous souhaitez spécifier form_class
dans la vue, comme vous l'avez fait dans le sous-classement de formulaire, spécifiez fields
dans le formulaire Meta
.
--Si vous ne spécifiez pas form_class
, spécifiez champs
dans la vue.
Vous souhaiterez peut-être également référencer des champs que vous ne modifiez pas à partir de formulaires ou de modèles.
Dans les deux cas, comme nous l'avons mentionné, vous pouvez utiliser les vues get_context_data ()
et get_form_kwargs ()
.
get_context_data ()
a été remplacée lors du passage des données de la vue au modèle.
--On a remplacé la méthode get_form_kwargs ()
lors du passage de données de la vue au formulaire.queryset
et l'interface utilisateur et la validation ont emboîté le pas.Recommended Posts