简体   繁体   English

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

[英]Django template: force choices on field and print display value with get_FOO_display()

I want a model with 5 choices, but I cannot enforce them and display the display value in template. 我想要一个具有5个选择的模型,但是我无法实施它们并在模板中显示显示值。 I am using CharField(choice=..) instead of ChoiceField or TypeChoiceField as in the docs . 我正在使用CharField(choice = ..)而不是docs中的ChoiceField或TypeChoiceField。 I tried the solutions here but they don't work for me (see below). 我在这里尝试了解决方案但是它们对我不起作用(请参阅下文)。

model.py: model.py:

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])

view.py view.py

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

mytemplate.html mytemplate.html

<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>

From shell: 从外壳:

python3 manage.py shell
from resume.models import Language
l1=Language.objects.create(language='English',level=4)
l1.save()
l1.get_level_display()   #This is good
Out[20]: 'Full professional proficiency'

As soon as I create a Language instance from shell I cannot load the site. 我从外壳程序创建语言实例后,就无法加载该站点。 It fails at line 0 of the template with Exception Type: KeyError, Exception Value: '4', Exception Location: /models.py in level_verbose, line 175 (which is the return line of the level_verbose method). 它在模板的第0行失败,其异常类型为:KeyError,异常值:'4',异常位置:在level_verbose的第175行(这是level_verbose方法的返回行)中的/models.py。

Also, I was expecting a validation error here from shell: 另外,我还期望shell出现验证错误:

l1.level='asdasd'
l1.save()     #Why can I save this instance with this level?

And I can also save a shown above when using ChoiceField, meaning that I do not understand what that field is used for. 而且,在使用ChoiceField时,我还可以保存上面显示的内容,这意味着我不了解该字段的用途。

How to force instances to take field values within choices, and display the display value in templates? 如何强制实例在选项中采用字段值,并在模板中显示显示值?

Well this is the common issue even when I started with django. 好吧,即使我从django开始,这也是常见的问题。 So first let's look at django's feature that you can do it like below (Note: your choice case's value are going to be store as integer so you should use models.IntegerField instead of models.CharField ): 因此,首先让我们看一下django的功能,您可以像下面那样进行操作(注意:您选择的情况下的值将存储为整数,因此您应该使用models.IntegerField而不是models.CharField ):

As you can see in documentation FOO is the field name of your model. 正如您在文档中所看到的, FOO是模型的字段名称。 in your case it is level so when you want to access corresponding choice value in shell or view you can call method with model instance as below as you have already mentioned: 在您的情况下,它是level因此当您要在shell或视图中访问相应的选择值时,可以使用如下所述的模型实例调用方法:

`l1.get_level_display()`

but when you want to access it in template file you need to write it like below: 但是当您想在模板文件中访问它时,您需要像下面这样写:

{{ l1.get_level_display }}
  • Now let's look at your method level_verbose() if you see quite again your model is a class and level_verbose() is the method you have created you can access self.ILR_scale directly just as you have used self.level 现在,让我们看一下您的方法level_verbose()如果您再次看到模型是一个类,而level_verbose()是您创建的方法,则可以像使用self.ILR_scale直接访问self.level

the main catch in you create dictionary of ILR_scale it's keys are Integer values (ie 1, 2, 3, 4, 5) but you have used CharField() to store the level values which returns you string values (ie '1', '2', '3', '4' or '5') and in python dictionary key 1 and '1' are both different one is integer and other is string. 在创建ILR_scale字典的过程中,主要要注意的是键值是整数值(ie 1, 2, 3, 4, 5)但是您已经使用CharField()存储了返回字符串值的电平值(ie '1', '2', '3', '4' or '5')并且在python字典中,键1和“ 1”都不同,一个是整数,另一个是字符串。 So you may change your model field to models.IntegerField() or you can access the keys like 因此,您可以将模型字段更改为models.IntegerField()或访问诸如

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

You can also use models.CharField but you have to set field option choices to your tuples. 您也可以使用models.CharField但必须将字段选项choices设置为元组。

For 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,
)

Then in your template you can use get_FOO_display() for example: {{l1.get_level_display}} 然后,您可以在模板中使用get_FOO_display()例如: {{l1.get_level_display}}

See more in docs 文档中查看更多

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM