请求从文档

时间:2016-01-07 14:37:22

标签: django choicefield

在官方文档中,https://docs.djangoproject.com/en/1.8/ref/models/fields/#choices我们得到了这个例子:

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)

YEAR_IN_SCHOOL_CHOICES的实际元组之前和之外,将变量设置为字符串的目的是什么? 这些字符串在哪里使用? 这些变量是否与元组中使用的变量相同? 如果是这样,为什么?这似乎是一个额外的,不必要的步骤。

在此之前的示例中,它们使用不同的 YEAR_IN_SCHOOL_CHOICES并没有帮助。谢谢你的澄清。

更新

由于我正在谈论这个代码,因此我感谢大家的快速反应。它们都为我的理解添加了一些东西。我认为@ shang-wang到目前为止对我的问题有最简洁和反应灵敏的答案。 1+用于get_FOO_display()的引用。但在我的特定用例中,管理员可以选择告诉最终用户如何评估特定对象。所以我想要人类可读的'评估的形式是最终html模板中显示给网站上最终用户的内容。鉴于这些答案,现在我想知道这是否是实现目标的最佳方式?是解决方案:

`

  

html显示表

对象名称|评价

FOO | foo.get_evaluation_display()

  

或者也许:

对象中的FOO:
对象名称|评价
FOO.name | foo.get_evaluation_display()
'

此特定模型的目的是向最终用户显示FOO的专家评估。每个FOO都可以有很多这样的评估。虽然通常非常冗长,但可以对这些评估进行分类,从而选择字段。然后,用户可以点击以完整阅读原始评估。因此,FOO在不同的模型上定义,并通过外键链接到评估模型。那么get_FOO_display()实际上会在这里工作,因为选择字段不在FOO是实例的模型上吗?

p.s,我意识到这已成为一个不同的问题,所以如果它需要被移动或其他什么,我可以用它,但它确实来自原来的q& a。让我知道。谢谢。

3 个答案:

答案 0 :(得分:1)

变量YEAR_IN_SCHOOL_CHOICES作为字段year_in_school中的所有可能选项提供。 YEAR_IN_SCHOOL_CHOICES中每对中的第一个值是将存储在数据库中的值,而每对中的第二个值将显示在表单下拉列表中(如果使用默认小部件)。像FRESHMAN = 'FR'这样的单独选择声明是为了确保它们被封装在类中。您可以为每个学生对象执行以下操作:

# 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

get_FOO_display的Django doc。

答案 1 :(得分:1)

文档似乎解释了示例后段落中的推理

  

虽然您可以在模型类之外定义选项列表然后   引用它,定义内部每个选择的选择和名称   model类将所有信息保存在使用它的类中,   并使选择易于参考(例如,Student.SOPHOMORE将   在导入学生模型的任何地方工作。

似乎他们认为制作选项类变量是个好主意,所以你永远不必引用原始值(例如'FR')。这也是为了确保您在导入此模型的任何地方都可以访问这些变量。

答案 2 :(得分: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.

为了避免以下用作类:      点击安装 enum34      进口检查 来自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)