Django模板:强制选择字段并使用get_FOO_display()打印显示值

时间:2018-03-04 04:06:07

标签: python django

我想要一个有5种选择的模型,但我无法强制执行它们并在模板中显示显示值。我在docs中使用CharField(choice = ..)而不是ChoiceField或TypeChoiceField。我尝试了解决方案here,但它们对我不起作用(见下文)。

model.py:

operator+=

view.py

operator+=

mytemplate.html

class Language(models.Model):
    language = models.CharField(max_length=20,blank=False)
    ILR_scale = (
        (5, 'Native'),
        (4, 'Full professional proficiency'),
        (3, 'Professional working proficiency'),
        (2, 'Limited professional proficiency'),
        (1, 'Elementary professional proficiency')
        )
    level = models.CharField(help_text='Choice between 1 and 5', default=5, max_length=25, choices=ILR_scale)
    def level_verbose(self):
        return dict(Language.ILR_scale)[self.level]
    class Meta:
        ordering = ['level','id']
    def __unicode__(self):
        return ''.join([self.language, '-', self.level])

来自shell:

..
def index(request):
language = Language.objects.all()
..

一旦我从shell创建一个语言实例,我就无法加载该站点。它在模板的第0行失败,具有异常类型:KeyError,异常值:'4',异常位置:/ level3中的/models.py,第175行(这是level_verbose方法的返回行)。

另外,我期待shell中的验证错误:

<div class="subheading strong-underlined mb-3 my-3">
      Languages
      </div>
      {% regroup language|dictsortreversed:"level" by level as level_list %}
      <ul>
        {% for lan_list in level_list %}
        <li>
          {% for lan in lan_list.list %}
          <strong>{{ lan.language }}</strong>: {{ lan.level_verbose }}{%if not forloop.last%},{%endif%}
          {% endfor %}
        </li>
        {% endfor %}
      </ul>

我还可以在使用ChoiceField时保存上面显示的内容,这意味着我不明白该字段的用途。

如何强制实例在选项中获取字段值,并在模板中显示显示值?

2 个答案:

答案 0 :(得分:2)

即使我开始使用django,这也是常见的问题。首先让我们看看django的功能,你可以像下面这样做(注意:你的选择案例值将存储为整数,所以你应该使用models.IntegerField代替models.CharField):

正如您在文档中看到的那样FOO是模型的字段名称。在你的情况下它是level所以当你想在shell或视图中访问相应的选择值时,你可以调用带有模型实例的方法,如下所示:

`l1.get_level_display()`

但是当你想在模板文件中访问它时,你需要像下面这样写它:

{{ l1.get_level_display }}
  • 现在让我们看一下您的方法level_verbose(),如果您再次看到您的模型是一个类,level_verbose()是您创建的方法,您可以直接访问self.ILR_scale正如您使用self.level

你创建ILR_scale字典的主要内容它的键是整数值(i.e. 1, 2, 3, 4, 5)但是你使用CharField()存储了返回字符串值(i.e. '1', '2', '3', '4' or '5')的级别值并在python词典键1和&#39; 1&#39;两者都不同,一个是整数,另一个是字符串。因此,您可以将模型字段更改为models.IntegerField(),也可以访问

等键
dict(self.ILR_scal)[int(self.level)]

答案 1 :(得分:0)

您也可以使用models.CharField,但必须为元组设置字段选项choices

exapmle:

FRESHMAN = 'FR'
SOPHOMORE = 'SO'
JUNIOR = 'JR'
SENIOR = 'SR'
LEVELS = (
    (FRESHMAN, 'Freshman'),
    (SOPHOMORE, 'Sophomore'),
    (JUNIOR, 'Junior'),
    (SENIOR, 'Senior'),
)
level = models.CharField(
    max_length=2,
    choices=LEVELS,
    default=FRESHMAN,
)

然后在您的模板中,您可以使用get_FOO_display()例如: {{l1.get_level_display}}

docs

中查看详情