2016-01-07 2 views
0

Dans les documents officiels, https://docs.djangoproject.com/en/1.8/ref/models/fields/#choices nous donne cet exemple:Demande de clarification de Django Code modèle Choix de Docs

class Student(models.Model): 
    FRESHMAN = 'FR' 
    SOPHOMORE = 'SO' 
    JUNIOR = 'JR' 
    SENIOR = 'SR' 
    YEAR_IN_SCHOOL_CHOICES = (
     (FRESHMAN, 'Freshman'), 
     (SOPHOMORE, 'Sophomore'), 
     (JUNIOR, 'Junior'), 
     (SENIOR, 'Senior'), 
    ) 
    year_in_school = models.CharField(max_length=2, 
             choices=YEAR_IN_SCHOOL_CHOICES, 
             default=FRESHMAN) 

Quel est le but de fixer les variables à chaînes avant, et en plus, la réelle tuples de YEAR_IN_SCHOOL_CHOICES? Où ces chaînes sont-elles utilisées? Ces variables sont-elles alors les mêmes que celles utilisées dans le tuple? Si oui, pourquoi? Cela semble être une étape supplémentaire et inutile.

Il n'est pas utile que dans l'exemple immédiatement avant celui-ci, ils utilisent différentsYEAR_IN_SCHOOL_CHOICES. Merci de clarifier.

MISE À JOUR

Depuis que je suis assis ici avec wrestling ce code que nous parlons, merci à tous pour les réponses rapides. Ils ajoutent tous quelque chose à ma compréhension. Je pense que @ shang-wang a la réponse la plus concise et la plus réactive à ma question jusqu'à présent. 1+ pour la référence à get_FOO_display(). Mais dans mon cas d'utilisation particulier, l'administrateur doit indiquer à l'utilisateur final comment un objet particulier a été évalué. Je veux donc que la forme «lisible par l'homme» des évaluations soit ce qui s'affiche dans le modèle html final pour l'utilisateur final sur le site. À la lumière de ces réponses, je me demande maintenant si c'est la meilleure façon d'atteindre mon objectif? La solution:

`

tableau d'affichage html

Nom de l'objet | Évaluation

FOO | foo.get_evaluation_display()

ou peut-être:

FOO dans les objets:
Nom de l'objet | Évaluation
FOO.name | foo.get_evaluation_display()
'

Le but de ce modèle particulier est d'afficher des évaluations expertes de FOO pour les utilisateurs finaux. Chaque FOO peut avoir plusieurs évaluations de ce type. Bien que généralement assez verbeux, ces évaluations peuvent être catégorisées, d'où le champ de choix. Les utilisateurs peuvent ensuite cliquer sur pour lire l'évaluation originale en entier s'ils le souhaitent. Ainsi, FOO est défini sur un modèle différent et est lié au modèle d'évaluation par une clé étrangère. Donc, get_FOO_display() fonctionnera-t-il ici, puisque le champ de choix n'est pas sur le modèle où FOO est une instance?

p.s, je me rends compte que ceci est maintenant devenu une question différente, donc si elle doit être déplacée ou autre chose, je suis d'accord avec ça, mais ça vient directement de l'original q & a. Faites le moi savoir. THX.

Répondre

1

La variable YEAR_IN_SCHOOL_CHOICES sert tous les choix possibles dans le champ year_in_school. La première valeur de chaque paire dans YEAR_IN_SCHOOL_CHOICES est celle qui sera stockée dans la base de données, tandis que la deuxième valeur dans chaque paire est celle qui apparaîtra dans la liste déroulante de votre formulaire (si vous utilisez le widget par défaut). La déclaration de sélection individuelle comme FRESHMAN = 'FR' est de s'assurer qu'ils sont encapsulés dans la classe.Vous pouvez effectuer les opérations suivantes pour chaque objet étudiant:

# assign the value to student's year_in_school 
student.year_in_school = Student.FRESHMAN 
student.save() 

# this will print 'FR' 
db_value = student.year_in_school 
print db_value 

# this will print 'Freshman' 
pretty_display_value = student.get_year_in_school_display() 
print pretty_display_value 

Django doc pour get_FOO_display.

1

La documentation semble expliquer le raisonnement suivi dans le paragraphe qui suit l'exemple

Bien que vous pouvez définir une liste de choix en dehors d'une classe de modèle puis s'y référer, définir les choix et les noms pour chaque choix à l'intérieur de la classe de modèle conserve toutes ces informations avec la classe qui l'utilise, et rend les choix faciles à référencer (par exemple, Student.SOPHOMORE fonctionne partout où le modèle étudiant a été importé).

Il semble qu'ils suggèrent qu'il est une bonne idée de la faire les options variables de classe afin que vous ne serez jamais se référer à la val brut (par exemple 'FR'). C'est aussi pour vous assurer que vous avez accès à ces variables partout où vous importez ce modèle.

1
# within your models.Model class... 
STUDENT_TYPE_CHOICES = (
    FRESHMAN = 'FR' 
    SOPHOMORE = 'SO' 
    JUNIOR = 'JR' 
    SENIOR = 'SR' 
) 
year_in_school = models.CharField(max_length=2, 
            choices=YEAR_IN_SCHOOL_CHOICES, 
            default=FRESHMAN) 




This means elsewhere in your code if you want to specify a choice field value, you’d have to enter the first slot of the tuple’s value, e.g.: 

year_in_school = models.objects.filter(year_in_school_type='SOPHOMORE') 


**This is pretty terrible** since it’s hardcoded in our source, possibly over many files. 

Pour éviter cette utilisation ci-dessous en tant que classe: pip install enum34 importation de inspectent Enum import ENUM

class ChoiceEnum(Enum): 

    @classmethod 
    def choices(cls): 
     # get all members of the class 
     members = inspect.getmembers(cls, lambda m: not(inspect.isroutine(m))) 
     # filter down to just properties 
     props = [m for m in members if not(m[0][:2] == '__')] 
     # format into django choice tuple 
     choices = tuple([(str(p[1].value), p[0]) for p in props]) 
     return choices 


**That’s the hard work over.** 

Now you create your choice field: 

from common.utils import ChoiceEnum 

class StudentTypes(ChoiceEnum): 
    FRESHMAN = 'FR' 
    SOPHOMORE = 'SO' 
    JUNIOR = 'JR' 
    SENIOR = 'SR' 

# within your models.Model class... 
year_in_school = models.CharField(max_length=1, choices=StudentTypes.choices()) 


Now if we need to access StudentTypes from elsewhere in our source code, we can simply: 

# import StudentTypes 
year_in_school = models.objects.filter(year_in_school=StudentTypes.junior.value)