Djangoテンプレート:選択の詳細バージョン


127

私はモデルを持っています:

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で利用可能ではないのですか?

回答:


258

Djangoテンプレートでは、「get_FOO_display()」メソッドを使用できます。これは、フィールドの読み取り可能なエイリアスを返します。「FOO」はフィールドの名前です。

注:標準FormPreviewテンプレートがテンプレートを使用していない場合は、そのフォームに独自のテンプレートをいつでも提供できます{{ form.get_meal_display }}。これにはのようなものが含まれます。


1
はい、知っています。しかし、それはそれほど一般的ではありません(ユニバーサル)-モデルオブジェクトのすべてのget_FOO_displayメソッドをテンプレートで反復する方法を知らない限り:)一般的ではないテンプレートを書くのは少し面倒です;)さらに、ドキュメントは言うこれはモデルインスタンスのメソッドです。したがって、既存のオブジェクトにバインドされたモデルフォームである必要がありますが、これは事実ではなく、一般的でもありません。
Artur Gajowy 2009

2
この使用法はビューに限定されないことに注意してください。get_FOO_display()はモデルオブジェクト自体のメソッドなので、モデルコードでも使用できます。たとえば、__ unicode __()では非常に便利です
Bogatyr 2014

51

問題に対する最善の解決策は、ヘルパー関数を使用することです。選択肢が変数CHOICESに格納され、選択した選択肢を格納するモデルフィールドが「choices」である場合は、直接使用できます。

 {{ x.get_choices_display }}

テンプレートで。ここで、xはモデルインスタンスです。それが役に立てば幸い。


3
有用な回答がすでに用意されている2年後、なぜこのように回答するのですか?そして、それを投票するのは誰ですか?@robertoわずか2年後のように、その同じ答え....
boatcoder

15
@ Mark0978この回答を賛成する理由は、(私にとって)「上位投票」の回答に従うほうが明確だったからです。YMMV。
Nir Levy

49

この回答が上記の一覧と重複している場合は申し訳ありませんが、これはまだ提供されていないようで、かなりきれいに見えます。これが私がこれを解決した方法です:

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をテンプレートに渡し(注:Scoop.values()ではありません)、テンプレートには以下が含まれています。

{{ scoop.flavor_verbose }}

10

ノアの返答に基づいて、選択のないフィールドに影響を受けないバージョンを次に示します。

#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

このような目的でフィルターを使用してもよいかどうかはわかりません。誰かがより良い解決策を持っているなら、私はそれを見てうれしいです:)ノアありがとう!


パスを言及するための+1#annoyances / templatetags / ... LOL ...フォームドキュメントの下部に記載されているget_FOO_display()を使用します。
fmalina

選択肢にhasattrを使うと素晴らしいアイデアです!
おでん2014

7

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)

かなり普遍的なようです:)それ以来、PythonやDjangoをあまり実行していないので、はっきりとはわかりません。しかし、それでもサードパーティ(Djangoには含まれていません)フィルターが必要なのはかなり悲しいです(そうでなければ、私たちに言ったでしょう、イヴァン、そうでしょうね;))...
Artur Gajowy

@ArturGajowyはい、現在のところ、Djangoにはそのようなデフォルトの機能はありません。私はそれを提案しました、誰が知っているか、多分それは承認されるでしょう
Ivan Kharlamov、2011年

パーフェクト!チャームのような作品!カスタムテンプレートフィルターROX!ありがとうございました!:-)
CeDeROM

5

それを行うための組み込みの方法はないと思います。ただし、フィルターでうまくいく場合があります。

@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 %}

3

models.pyに単純な関数を1つ追加します。

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)    

更新:よくわかりませんが、そのソリューションは「pythonic」と「django-way」で十分かどうかはわかりませんが、機能します。:)


0

Model.get_FOO_display()があり、FOOは選択肢があるフィールドの名前です。

テンプレートでこれを行います:

{{ scoop.get_flavor_display }}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.