2009-07-09 128 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