2009-07-09 93 views
98

的详细的版本我有一个模型:Django模板:选择

from django.db import models 

CHOICES = (
    ('s', 'Glorious spam'), 
    ('e', 'Fabulous eggs'), 
) 

class MealOrder(models.Model): 
    meal = models.CharField(max_length=8, choices=CHOICES) 

我有一个表格:

from django.forms import ModelForm 

class MealOrderForm(ModelForm): 
    class Meta: 
     model = MealOrder 

而且我想用formtools.preview。默认模板打印选择(而不是“神话般的蛋”的“e”)的短版,原因是其使用

{% for field in form %} 
<tr> 
<th>{{ field.label }}:</th> 
<td>{{ field.data }}</td> 
</tr> 
{% endfor %}. 

我想一个模板作为一般的提及,但打印“神话般的蛋'而是。

[我不得不怀疑其中的真正的问题,我粗体它为我们所有的:)]

我知道怎么去选择的详细的版本的方式,本身是丑陋的:

{{ form.meal.field.choices.1.1 }} 

真正的痛苦是我需要选择的选择,并且来我心中的唯一方法是通过选择迭代和检查{% ifequals currentChoice.0 choiceField.data %},这甚至丑陋。

它可以轻松完成吗?或者它需要一些模板标签编程?不应该在django中可用吗?

回答

4

我不认为有任何内置的方式来做到这一点。过滤器可能会做的伎俩,虽然:

@register.filter(name='display') 
def display_value(bf): 
    """Returns the display value of a BoundField""" 
    return dict(bf.field.choices).get(bf.data, '') 

然后,你可以这样做:

{% for field in form %} 
    <tr> 
     <th>{{ field.label }}:</th> 
     <td>{{ field.data|display }}</td> 
    </tr> 
{% endfor %} 
208

在Django模板,你可以使用“get_FOO_display()”的方法,这将返回可读别名场,其中“FOO”是该字段的名称。

注意:如果标准FormPreview模板没有使用它,那么您可以始终使用provide your own templates表格,其中将包含类似{{ form.get_meal_display }}的内容。

+1

是的,我知道。它不是普通的(通用的),但是 - 除非你知道在模板对象的所有get_FOO_display方法中遍历模板的方法:)对于编写非通用模板,我有点太懒惰;) 此外,文档说这是一个模型实例的方法。因此,它必须是一个绑定到现有对象的模型形式,而不是这种情况,也不是一般的。 – 2009-07-09 22:40:48

+0

我一直在忘记这一个 – Sevenearths 2011-09-23 09:55:26

+2

请注意,这个用法不限于视图,get_FOO_display()是模型对象本身的一个方法,所以您也可以在模型代码中使用它!例如,在__unicode __()中,非常方便 – Bogatyr 2014-02-27 17:13:40

9

基础上诺亚的答复,这里有一个版本免疫字段,而选择:

#annoyances/templatetags/data_verbose.py 
from django import template 

register = template.Library() 

@register.filter 
def data_verbose(boundField): 
    """ 
    Returns field's data or it's verbose version 
    for a field with choices defined. 

    Usage:: 

     {% load data_verbose %} 
     {{form.some_field|data_verbose}} 
    """ 
    data = boundField.data 
    field = boundField.field 
    return hasattr(field, 'choices') and dict(field.choices).get(data,'') or data 

我不知道羯羊它的确定使用过滤器用于此目的。如果有人有更好的解决方案,我会很高兴看到它:)谢谢诺亚!

+0

提及你的路径#烦人/ templatetags/... LOL ...我使用get_FOO_display(),它在表单文档的底部提到。 – 2011-02-15 15:04:02

+0

使用hasattr选项的好主意! – oden 2014-07-07 06:56:05

6

我们可以通过Noah延长过滤器的解决方案是在处理数据和字段类型更加普遍:

<table> 
{% for item in query %} 
    <tr> 
     {% for field in fields %} 
      <td>{{item|human_readable:field}}</td> 
     {% endfor %} 
    </tr> 
{% endfor %} 
</table> 

下面的代码:

#app_name/templatetags/custom_tags.py 
def human_readable(value, arg): 
    if hasattr(value, 'get_' + str(arg) + '_display'): 
     return getattr(value, 'get_%s_display' % arg)() 
    elif hasattr(value, str(arg)): 
     if callable(getattr(value, str(arg))): 
      return getattr(value, arg)() 
     else: 
      return getattr(value, arg) 
    else: 
     try: 
      return value[arg] 
     except KeyError: 
      return settings.TEMPLATE_STRING_IF_INVALID 
register.filter('human_readable', human_readable) 
35

有关问题的最佳解决方案是使用助手功能。 如果选择存储在变量的选择和模型字段存储选择的选择是“选择”,那么你可以直接在模板中使用

{{ x.get_choices_display }} 

。这里,x是模型实例。 希望它有帮助。

2

添加到您的models.py一个简单的函数:

def get_display(key, list): 
    d = dict(list) 
    if key in d: 
     return d[key] 
    return None 

现在,你可以选择字段像的详细值:

class MealOrder(models.Model): 
    meal = models.CharField(max_length=8, choices=CHOICES) 

    def meal_verbose(self): 
     return get_display(self.meal, CHOICES)  

UPD:我不知道,解决方案“pythonic”和“django-way”足够或不是,但它的工作原理。 :)

25

我的道歉,如果这个答案是多余的任何上面列出,但它似乎这一个尚未提供,并且它似乎很干净。以下是我已经解决了这个:

from django.db import models 

class Scoop(models.Model): 
    FLAVOR_CHOICES = [ 
     ('c', 'Chocolate'), 
     ('v', 'Vanilla'), 
    ] 

    flavor = models.CharField(choices=FLAVOR_CHOICES) 

    def flavor_verbose(self): 
     return dict(Scoop.FLAVOR_CHOCIES)[self.flavor] 

我的观点传递舀到模板(注: Scoop.values()),以及模板包含:

{{ scoop.flavor_verbose }} 
-2

随着使用模板标签。

与Arthur Gawjowj几乎相同,但是这个选项只用于使用整数值而不是字符串。

# project/templatetags/project_tags.py 

from django.template.base import Library 


register = Library() 

@register.filter(name='pretty_form_value') 
def pretty_form_value(field): 
    """ 
    Returns field's data or it's verbose version 
    for a field with choices defined. 

    Usage:: 

     {% load project_tags %} 
     {{form.some_field|pretty_form_value}} 
    """ 
    if hasattr(field.field, 'choices'): 
     try: 
      return dict(field.field.choices)[int(field.data)] 
     except ValueError: 
      pass 
    return field.data