在官方文档中,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。让我知道。谢谢。
答案 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)