web-dev-qa-db-fra.com

Comment utiliser correctement l’option de champ "choices" dans Django

Je lis le tutoriel ici: https://docs.djangoproject.com/fr/1.5/ref/models/fields/#choices et j'essaie de créer une boîte où l'utilisateur peut sélectionnez le mois de sa naissance. Ce que j’ai essayé était

 MONTH_CHOICES = (
    (JANUARY, "January"),
    (FEBRUARY, "February"),
    (MARCH, "March"),
    ....
    (DECEMBER, "December"),
)

month = CharField(max_length=9,
                  choices=MONTHS_CHOICES,
                  default=JANUARY)

Est-ce correct? Je vois que dans le tutoriel que je lisais, ils ont d'abord créé des variables, comme

FRESHMAN = 'FR'
SOPHOMORE = 'SO'
JUNIOR = 'JR'
SENIOR = 'SR'

Pourquoi ont-ils créé ces variables? En outre, MONTHS_CHOICES est dans un modèle appelé People, le code que j'ai fourni créerait donc une colonne "Mois" dans la base de données appelée "People" et indiquerait le mois de naissance de l'utilisateur après avoir cliqué sur l'un des mois. et soumet le formulaire?

36
user2719875

Selon le documentation :

Field.choices

Une variable (par exemple, une liste ou un nuplet) se composant d’itérables de deux éléments exactement (par exemple [(A, B), (A, B) ...]) à utiliser comme choix pour ce champ. Si cela est indiqué, le widget de formulaire par défaut sera une zone de sélection avec ces choix au lieu du champ de texte standard.

Le premier élément de chaque tuple est la valeur réelle à stocker, et le deuxième élément est le nom lisible par l'homme.

Votre code est donc correct, sauf que vous devez soit définir les variables JANUARY, FEBRUARY etc., soit utiliser le module calendar pour définir MONTH_CHOICES:

import calendar

...

class MyModel(models.Model):
    ...

    MONTH_CHOICES = [(str(i), calendar.month_name[i]) for i in range(1,13)]

    month = CharField(max_length=9, choices=MONTHS_CHOICES, default='1')
28
alecxe

Je pense que personne n'a réellement répondu à la première question:

Pourquoi ont-ils créé ces variables?

Ces variables ne sont pas strictement nécessaires. C'est vrai. Vous pouvez parfaitement faire quelque chose comme ça:

MONTH_CHOICES = (
    ("JANUARY", "January"),
    ("FEBRUARY", "February"),
    ("MARCH", "March"),
    # ....
    ("DECEMBER", "December"),
)

month = models.CharField(max_length=9,
                  choices=MONTH_CHOICES,
                  default="JANUARY")

Pourquoi utiliser des variables, c'est mieux? Prévention des erreurs et séparation logique.

JAN = "JANUARY"
FEB = "FEBRUARY"
MAR = "MAR"
# (...)

MONTH_CHOICES = (
    (JAN, "January"),
    (FEB, "February"),
    (MAR, "March"),
    # ....
    (DEC, "December"),
)

Maintenant, imaginez que vous ayez une vue où vous créez une nouvelle instance de modèle. Au lieu de faire ceci:

new_instance = MyModel(month='JANUARY')

Vous allez faire ceci:

new_instance = MyModel(month=MyModel.JAN)

Dans la première option, vous codez en dur la valeur. Si vous pouvez saisir un ensemble de valeurs, limitez ces options lors du codage. De même, si vous devez éventuellement modifier le code au niveau de la couche Modèle, vous n'avez plus besoin de modifier la couche Vues.

94
JCJS

La solution la plus propre consiste à utiliser le Django-model-utils bibliothèque:

from model_utils import Choices

class Article(models.Model):
    STATUS = Choices('draft', 'published')
    status = models.CharField(choices=STATUS, default=STATUS.draft, max_length=20)

https://Django-model-utils.readthedocs.io/en/latest/utilities.html#choices

4
Babken Vardanyan

Vous ne pouvez pas avoir de mots nus dans le code, c'est la raison pour laquelle ils ont créé des variables (votre code échouera avec NameError).

Le code que vous avez fourni créerait une table de base de données nommée month (plus le préfixe Django s'ajoute à cela), car c'est le nom du CharField.

Mais il existe de meilleurs moyens de créer les choix que vous souhaitez. Voir ne question précédente de Stack Overflow .

import calendar
Tuple((m, m) for m in calendar.month_name[1:])
3
Paulo Almeida