Python 如何在 Django 中正确使用“选择”字段选项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18676156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to properly use the "choices" field option in Django
提问by user2719875
I'm reading the tutorial here: https://docs.djangoproject.com/en/1.5/ref/models/fields/#choicesand i'm trying to create a box where the user can select the month he was born in. What I tried was
我在这里阅读教程:https: //docs.djangoproject.com/en/1.5/ref/models/fields/#choices,我正在尝试创建一个框,用户可以在其中选择他出生的月份. 我试过的是
MONTH_CHOICES = (
(JANUARY, "January"),
(FEBRUARY, "February"),
(MARCH, "March"),
....
(DECEMBER, "December"),
)
month = CharField(max_length=9,
choices=MONTHS_CHOICES,
default=JANUARY)
Is this correct? I see that in the tutorial I was reading, they for some reason created variables first, like so
这样对吗?我看到在我正在阅读的教程中,他们出于某种原因首先创建了变量,就像这样
FRESHMAN = 'FR'
SOPHOMORE = 'SO'
JUNIOR = 'JR'
SENIOR = 'SR'
Why did they create those variables? Also, the MONTHS_CHOICES is in a model called People, so would the code I provided create a "Months Choices) column in the database called called "People" and would it say what month the user was born in after he clicks on of the months and submits the form?
他们为什么要创建这些变量?此外,MONTHS_CHOICES 在一个名为 People 的模型中,所以我提供的代码会在名为“People”的数据库中创建一个“Months Choices)列,并说明用户在点击月份后出生的月份并提交表格?
采纳答案by alecxe
According to the documentation:
根据文档:
Field.choices
An iterable (e.g., a list or tuple) consisting itself of iterables of exactly two items (e.g. [(A, B), (A, B) ...]) to use as choices for this field. If this is given, the default form widget will be a select box with these choices instead of the standard text field.
The first element in each tuple is the actual value to be stored, and the second element is the human-readable name.
现场选择
一个可迭代对象(例如,列表或元组)由恰好两个项目(例如 [(A, B), (A, B) ...])的可迭代对象组成,用作该字段的选择。如果给出了这个,默认的表单小部件将是一个带有这些选项的选择框,而不是标准的文本字段。
每个元组中的第一个元素是要存储的实际值,第二个元素是人类可读的名称。
So, your code is correct, except that you should either define variables JANUARY
, FEBRUARY
etc. or use calendar
module to define MONTH_CHOICES
:
所以,你的代码是正确的,但您应该定义变量JANUARY
,FEBRUARY
等,或使用calendar
模块定义MONTH_CHOICES
:
import calendar
...
class MyModel(models.Model):
...
MONTH_CHOICES = [(str(i), calendar.month_name[i]) for i in range(1,13)]
month = models.CharField(max_length=9, choices=MONTH_CHOICES, default='1')
回答by Paulo Almeida
You can't have bare words in the code, that's the reason why they created variables (your code will fail with NameError
).
您不能在代码中使用裸词,这就是它们创建变量的原因(您的代码将失败并显示NameError
)。
The code you provided would create a database table named month
(plus whatever prefix django adds to that), because that's the name of the CharField
.
您提供的代码将创建一个名为month
(加上 django 添加的任何前缀)的数据库表,因为这是CharField
.
But there are better ways to create the particular choices you want. See a previous Stack Overflow question.
但是有更好的方法来创建您想要的特定选择。请参阅上一个堆栈溢出问题。
import calendar
tuple((m, m) for m in calendar.month_name[1:])
回答by JCJS
I think no one actually has answered to the first question:
我认为没有人真正回答过第一个问题:
Why did they create those variables?
他们为什么要创建这些变量?
Those variables aren't strictly necessary. It's true. You can perfectly do something like this:
这些变量并不是绝对必要的。这是真的。你可以完美地做这样的事情:
MONTH_CHOICES = (
("JANUARY", "January"),
("FEBRUARY", "February"),
("MARCH", "March"),
# ....
("DECEMBER", "December"),
)
month = models.CharField(max_length=9,
choices=MONTH_CHOICES,
default="JANUARY")
Why using variables is better? Error prevention and logic separation.
为什么使用变量更好?错误预防和逻辑分离。
JAN = "JANUARY"
FEB = "FEBRUARY"
MAR = "MAR"
# (...)
MONTH_CHOICES = (
(JAN, "January"),
(FEB, "February"),
(MAR, "March"),
# ....
(DEC, "December"),
)
Now, imagine you have a view where you create a new Model instance. Instead of doing this:
现在,假设您有一个视图,您可以在其中创建一个新的 Model 实例。而不是这样做:
new_instance = MyModel(month='JANUARY')
You'll do this:
你会这样做:
new_instance = MyModel(month=MyModel.JAN)
In the first option you are hardcoding the value. If there is a set of values you can input, you should limit those options when coding. Also, if you eventually need to change the code at the Model layer, now you don't need to make any change in the Views layer.
在第一个选项中,您对值进行了硬编码。如果您可以输入一组值,则应在编码时限制这些选项。此外,如果您最终需要更改 Model 层的代码,现在您无需在 Views 层进行任何更改。
回答by Babken Vardanyan
The cleanest solution is to use the django-model-utils
library:
最干净的解决方案是使用django-model-utils
库:
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
https://django-model-utils.readthedocs.io/en/latest/utilities.html#choices
回答by dtar
I would suggest to use django-model-utilsinstead of Django built-in solution. The main advantage of this solution is the lack of string declaration duplication. All choice items are declared exactly once. Also this is the easiest way for declaring choices using 3 values and storing database value different than usage in source code.
我建议使用django-model-utils而不是 Django 内置解决方案。此解决方案的主要优点是没有重复的字符串声明。所有选择项都只声明一次。这也是使用 3 个值声明选择并存储与源代码中的用法不同的数据库值的最简单方法。
from django.utils.translation import ugettext_lazy as _
from model_utils import Choices
class MyModel(models.Model):
MONTH = Choices(
('JAN', _('January')),
('FEB', _('February')),
('MAR', _('March')),
)
# [..]
month = models.CharField(
max_length=3,
choices=MONTH,
default=MONTH.JAN,
)
And with usage IntegerField instead:
并使用 IntegerField 代替:
from django.utils.translation import ugettext_lazy as _
from model_utils import Choices
class MyModel(models.Model):
MONTH = Choices(
(1, 'JAN', _('January')),
(2, 'FEB', _('February')),
(3, 'MAR', _('March')),
)
# [..]
month = models.PositiveSmallIntegerField(
choices=MONTH,
default=MONTH.JAN,
)
- This method has one small disadvantage: in any IDE (eg. PyCharm) there will be no code completion for available choices (it's because those values aren't standard members of Choices class).
- 这种方法有一个小缺点:在任何 IDE(例如 PyCharm)中,对于可用选项都没有代码补全(这是因为这些值不是 Choices 类的标准成员)。
回答by Waket Zheng
For Django3.0+, use models.TextChoices
(see docs-v3.0for enumeration types)
对于Django3.0 +,使用models.TextChoices
(见文档-V3.0的枚举类型)
from django.db import models
class MyModel(models.Model):
class Month(models.TextChoices):
JAN = '1', "JANUARY"
FEB = '2', "FEBRUARY"
MAR = '3', "MAR"
# (...)
month = models.CharField(
max_length=2,
choices=Month.choices,
default=Month.JAN
)