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를 사용하고 싶습니다. 기본 템플릿은 짧은 버전의 선택 ( '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 %}하는 것입니다.

쉽게 할 수 있습니까? 아니면 템플릿 태그 프로그래밍이 필요합니까? 장고에서 이미 사용 가능하지 않아야합니까?

답변:


258

Django 템플릿에서 "get_FOO_display() "메서드를 사용하면 필드의 읽을 수있는 별칭을 반환합니다. 여기서 'FOO'는 필드 이름입니다.

참고 : 표준 FormPreview템플릿에서 사용하지 않는 경우 언제든지 해당 양식에 대해 자신 만의 템플릿제공 할 수 있습니다 {{ form.get_meal_display }}.


1
예, 알아요 그래도 일반적인 (범용)은 아닙니다-모델 객체의 모든 get_FOO_display 메소드에 대해 템플릿에서 반복하는 방법을 모르면 :) 제네릭이 아닌 템플릿을 작성하기에는 너무 게으 릅니다.) 모델 인스턴스의 방법입니다. 따라서 일반적인 개체가 아닌 기존 개체에 바인딩 된 모델 형식이어야합니다.
Artur Gajowy

2
이 사용법은 뷰에 국한되지 않으며 get_FOO_display ()는 모델 객체 자체의 메소드이므로 모델 코드에서도 사용할 수 있습니다! 예를 들어 __unicode __ ()에서는 매우 편리합니다.
Bogatyr

51

문제에 대한 가장 좋은 해결책은 도우미 기능을 사용하는 것입니다. 선택 사항이 변수 CHOICES에 저장되고 선택한 선택 사항을 저장하는 모델 필드가 ' 선택 사항 '인 경우 직접 사용할 수 있습니다.

 {{ x.get_choices_display }}

템플릿에서. 여기서 x는 모델 인스턴스입니다. 도움이 되길 바랍니다.


3
유용한 답변이 이미 준비된 후 2 년 동안 왜 이렇게 대답 하시겠습니까? 누가 투표할까요? 2 년 후 @roberto과 같은 대답입니다 ....
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.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 ... 나는 do_FOO_display ()를 사용하는데, 이는 docs 양식의 하단에 언급되어 있습니다.
fmalina

선택에 hasattr을 사용하는 좋은 아이디어!
oden

7

데이터 및 필드 유형을 처리하는 데보다 보편적 으로 노아 의 필터 솔루션을 확장 할 수 있습니다.

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

꽤 보편적 인 것 같습니다 :) 그 이후로 파이썬이나 장고를 너무 많이하지 않았기 때문에 확실하게 말할 수 없습니다. ...) (? 그렇지 않으면 당신은 당신이없는 것, 이반 우리를 말할 것) 그것은 여전히 (장고에 포함되지 않음) 제 3 자 필터를 필요로하지만, 아주 슬픈
아르투르 Gajowy

@ArturGajowy 네, 오늘 장고에는 그러한 기본 기능이 없습니다. 나는 아마 그것이 승인 될 것이라고 제안했다 .
Ivan Kharlamov

완전한! 참처럼 작동합니다! 커스텀 템플릿 필터 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에 하나의 간단한 함수를 추가하십시오.

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"가 충분하지 않더라도 작동합니다. :)


0

Model.get_FOO_display ()가 있습니다. 여기서 FOO는 선택 사항이있는 필드의 이름입니다.

템플릿에서 다음을 수행하십시오.

{{ scoop.get_flavor_display }}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.