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 का उपयोग करना चाहता हूं। डिफ़ॉल्ट टेम्पलेट पसंद के छोटे संस्करण ('शानदार अंडे' के बजाय 'ई') को प्रिंट करता है, इसे उपयोग करता है

{% 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 तरीकों पर टेम्पलेट में पुनरावृति करने का एक तरीका नहीं जानते हैं :) मैं गैर-जेनेरिक टेम्पलेट लिखने के लिए थोड़ा बहुत आलसी हूं;) इसके अलावा, घबराहट का कहना है; यह एक मॉडल उदाहरण की विधि है। इसलिए यह एक मौजूदा उद्देश्य के लिए बाध्य एक मॉडल रूप होना चाहिए जो मामला नहीं है और सामान्य भी नहीं है।
अर्तुर गजोजी

2
ध्यान दें कि यह उपयोग केवल विचारों तक सीमित नहीं है, get_FOO_display () मॉडल ऑब्जेक्ट पर ही एक विधि है इसलिए आप इसे मॉडल कोड में भी उपयोग कर सकते हैं! उदाहरण के लिए, __unicode __ () में यह बहुत उपयोगी है
बोगाटायर

51

आपकी समस्या का सबसे अच्छा समाधान सहायक कार्यों का उपयोग करना है। यदि विकल्प चर CHOICES में संग्रहीत हैं और चयनित विकल्प को संग्रहीत करने वाला मॉडल फ़ील्ड ' विकल्प ' है तो आप सीधे उपयोग कर सकते हैं

 {{ x.get_choices_display }}

अपने टेम्पलेट में। यहाँ, x मॉडल उदाहरण है। आशा करता हूँ की ये काम करेगा।


3
एक उपयोगी उत्तर पहले से मौजूद होने के बाद आप इस तरह 2 साल का जवाब क्यों देंगे? और इसे कौन वोट देगा? इसका ठीक 2 साल बाद
@roberto

15
@ Mark0978 इस उत्तर को बनाए रखने का कारण है क्योंकि (मेरे लिए) यह "शीर्ष मतदान" उत्तर का पालन करने के लिए स्पष्ट था। YMMV।
नीर लेवी

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

मुझे यकीन नहीं है कि इस तरह के उद्देश्य के लिए एक फिल्टर का उपयोग करना ठीक है। अगर किसी के पास एक बेहतर समाधान है, तो मुझे इसे देखकर खुशी होगी :) धन्यवाद नूह!


अपने पथ # झुंझलाहट / templatetags / ... LOL ... का उल्लेख करने के लिए +1, मैं get_FOO_display () का उपयोग करता हूं, जो फ़ॉर्म डॉक्स के नीचे उल्लेखित है।
फेलिना

विकल्पों पर 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)

काफी सार्वभौमिक लगता है :) निश्चित रूप से नहीं बता सकता, क्योंकि मैंने उस समय से बहुत अधिक पायथन या Django नहीं किया है। हालांकि, यह बहुत दुख की बात है, कि इसे अभी भी एक 3 पार्टी की आवश्यकता है (Django में शामिल नहीं) फ़िल्टर (अन्यथा आप हमें बताएंगे, इवान, आपको नहीं?);) ...
आर्टूर गजोवी

@ArturGajowy हाँ, आज तक Django में ऐसी कोई डिफ़ॉल्ट सुविधा नहीं है। मैंने इसे प्रस्तावित किया है, जो जानता है, शायद इसे मंजूरी दी जाएगी
इवान खारलामोव

उत्तम! एक जादू की तरह काम करता है! कस्टम फिल्टर फिल्टर 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

अपने मॉडल में जोड़ें एक साधारण फ़ंक्शन:

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)    

अद्यतन: मुझे यकीन नहीं है, क्या वह समाधान "पाइथोनिक" और "डीजेगो-वे" पर्याप्त है या नहीं, लेकिन यह काम करता है। :)


0

आपके पास Model.get_FOO_display () है जहां FOO उस क्षेत्र का नाम है जिसमें विकल्प हैं।

अपने टेम्पलेट में यह करें:

{{ scoop.get_flavor_display }}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.