[django] 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를 사용하고 싶습니다. 기본 템플릿은 짧은 버전의 선택 ( ‘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 템플릿에서 “get_FOO_display() “메서드를 사용하면 필드의 읽을 수있는 별칭을 반환합니다. 여기서 ‘FOO’는 필드 이름입니다.

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


답변

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

 {{ x.get_choices_display }}

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


답변

이 답변이 위에 나열된 내용과 중복되는 경우 사과하지만 아직 제공되지 않은 것으로 보이며 상당히 깨끗해 보입니다. 이 문제를 해결 한 방법은 다음과 같습니다.

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


답변

노아의 대답을 바탕으로 선택하지 않은 분야에 면역성이있는 버전이 있습니다.

#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

그런 목적으로 필터를 사용해도 괜찮습니다. 더 나은 솔루션을 가진 사람이 있다면 기뻐할 것입니다. : 노아 감사합니다!


답변

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

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


답변

나는 그것을 할 수있는 내장 방법이 없다고 생각합니다. 그러나 필터는 다음과 같은 트릭을 수행 할 수 있습니다.

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


답변

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