Divisez les données en unités de type projet avec Django (2)

Préface

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)

Contenu de l'article

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.

Objectifs spécifiques

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')
Ajouter des personnages.png

▲ Vous pouvez choisir les acteurs d'autres performances.

Organisez ce que vous voulez faire

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».

Interface utilisateur pour sélectionner une distribution

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.

Validation

É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».

Lors de l'édition ultérieure

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éé.

Modifications de l'interface utilisateur

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}}.

Modifier le contenu du formulaire

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

Explication détaillée

--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.

Ajout de caractères 2.png

▲ Seuls les acteurs de la performance auxquels appartiennent les personnages étaient affichés.

Validation

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».

Altérer.png

▲ Essayez de falsifier les options de votre navigateur.

J'ai pu ajouter.png

▲ La valeur altérée a été ajoutée.

Modifier les résultats de la validation

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.

Explication détaillé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é.

La partie désagréable de ceci

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.

Une autre façon (sous-classer la forme)

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".

Passer les données au formulaire

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

Implémentation côté formulaire

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".

Repoussé.png

Lors de l'édition ultérieure

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 ".

Modifier les champs modifiables

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.

Je ne le modifie pas, mais je veux y faire référence

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 ().

Résumé

J'ai écrit la suite

Recommended Posts

Divisez les données en unités de type projet avec Django (2)
Divisez les données en unités de type projet avec Django (3)
Divisez les données en unités de type projet avec Django
Utilisez Django pour enregistrer les données de tweet
Diviser le japonais (katakana) en syllabes [Python]
Générer et publier des données d'image factice avec Django
Internationalisation avec Django
CRUD avec Django
Transformez les données de vacances en une trame de données avec les pandas
Essayez de diviser les données Twitter en SPAM et HAM
Divisez l'ensemble de données (ndarray) en proportions arbitraires avec NumPy
Authentifier Google avec Django
Analyse de données avec python 2
Télécharger des fichiers avec Django
Résumé du développement avec Django
Sortie PDF avec Django
Sortie Markdown avec Django
Twitter OAuth avec Django
Lecture de données avec TensorFlow
Premiers pas avec Django 1
Envoyer des e-mails avec Django
Téléchargement de fichiers avec django
Visualisation des données avec les pandas
Manipulation des données avec les Pandas!
Utilisez LESS avec Django
Mélangez les données avec les pandas
La mutualisation mécanise avec Django
Augmentation des données avec openCV
Utiliser MySQL avec Django
Normariser les données avec Scipy
Analyse de données avec Python
Django à partir d'aujourd'hui
CHARGER DES DONNÉES avec PyMysql
Premiers pas avec Django 2
Technique élégante pour coller des données CSV dans Excel avec Python