web-dev-qa-db-ja.com

Django templates:選択の冗長バージョン

私にはモデルがあります:

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を使用したいと思います。デフォルトのテンプレートは、選択の短いバージョン(「Fabulous eggs」ではなく「e」)を出力します。

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

前述のように一般的なテンプレートが欲しいのですが、代わりに「Fabulous eggs」を印刷します。

[本当の質問はどこにあるのか疑っていたので、私たち全員のために太字にしました:)]

私はそれ自体がい方法で選択の冗長バージョンを取得する方法を知っています:

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

本当の痛みは、選択した選択肢を取得する必要があることです。頭に浮かぶ唯一の方法は、選択肢を繰り返して確認することです{% ifequals currentChoice.0 choiceField.data %}、さらにいです。

簡単にできますか?または、テンプレートタグのプログラミングが必要ですか? Django=で既に利用可能になっていないはずですか?

116
Artur Gajowy

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

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

237
rob

問題に対する最善の解決策は、ヘルパー関数を使用することです。選択肢が変数[〜#〜] choices [〜#〜]に保存され、選択された選択肢を保存するモデルフィールドが 'choices'である場合、直接使用できます。

 {{ x.get_choices_display }}

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

43
Reema

この回答が上記のリストと重複している場合はおaび申し上げますが、この回答はまだ提供されていないようです。これを私が解決した方法は次のとおりです。

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をテンプレートに渡し(注:not Scoop.values())、テンプレートには以下が含まれます:

{{ scoop.flavor_verbose }}
39
Dan Kerchner

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

#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

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

9
Artur Gajowy

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)
6
Ivan Kharlamov

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

@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 %}
5
Noah Medling

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」で十分かどうかですが、うまくいきます。 :)

3