2013-06-11 8 views
5

मैं एक django टेम्पलेट लिख रहा हूं और मैं अस्तित्व के बीच एक संदर्भ चर के बनाम अंतर, खाली आदि के बीच अंतर करना चाहता हूं। मैंने अपना होमवर्क किया है और यह आश्चर्यजनक रूप से कठिन लगता है। विशेष रूप से, यह है कि क्या मैंdjango टेम्पलेट संदर्भ परिवर्तनीय के अस्तित्व की जांच

view 1: 
... 
if some_condition = True: 
    context['letters'] = ['a', 'b', 'c'] # The list might also be empty or None in some cases 
else 
    context['numbers'] = [1, 2, 3] #This list might be empty or None in some cases 

Template 
... 
<ul> 
{% if letters %} 
    {% for x in letter %} 
     <li>{{x}}</li> 
    {%endfor%} 
{% else %} 
    {%for x in numbers%} 
     <li>{{x}}</li> 
    {%endfor%} 
</ul> 

करने के लिए उपयोग करना {% if %} dicey है, क्योंकि यह है विफल रहता है letters does not मौजूद या सूची रिक्त है कोशिश कर रहा हूँ है। मैं letters उपयोग करना चाहते हैं, भले ही वह खाली (लेकिन संदर्भ में परिभाषित)

मैं निर्मित फिल्टर default और default_if_none मैं कैसे से यह अन्य किया जा रहा है एक संदर्भ चर के अस्तित्व अंतर कर सकते हैं के साथ एक ही समस्या है है कोई भी चीज़ या खाली

उत्तर

4

मैं हाल ही में एक ही पहेली का सामना करना पड़ा, और जिस तरह {% if %} टैग यहाँ संरचित है में देखने के बाद क्या मैं के साथ आया था:

from django.template.base import VariableDoesNotExist 
from django.template.defaulttags import IfNode 
from django.template.smartif import IfParser, Literal 

# Used as a value for ifdef and ifndef tags 
undefined = object() 

class IfDefLiteral(Literal): 
    def eval(self, context): 
     if not self.value in context: 
      # Can't raise an exception here because Operator catches it 
      return undefined 

class IfDefParser(IfParser): 
    def create_var(self, value): 
     return IfDefLiteral(value) 

class IfDefNode(IfNode): 
    def __init__(self, defined=True, *args, **kwargs): 
     self.defined = defined 
     super(IfDefNode, self).__init__(*args, **kwargs) 

    def __repr__(self): 
     return "<%s>" % self.__class__.__name__ 

    def render(self, context): 
     for condition, nodelist in self.conditions_nodelists: 

      match = undefined 
      if condition is not None:   # if/elif clause 
       try: 
        match = condition.eval(context) 
       except VariableDoesNotExist: 
        pass 

      if condition is None or ( # else clause, always render 
       (self.defined and match is not undefined) or 
       (match is undefined and not self.defined)): 
       return nodelist.render(context) 

     return '' 

def _gen_ifdef(parser, token, block_tokens, defined): 
    # {% if ... %} 
    bits = token.split_contents()[1:] 
    condition = IfDefParser(bits).parse() 
    nodelist = parser.parse(block_tokens) 
    conditions_nodelists = [(condition, nodelist)] 
    token = parser.next_token() 

    # {% elif ... %} (repeatable) 
    while token.contents.startswith(block_tokens[0]): 
     bits = token.split_contents()[1:] 
     condition = IfDefParser(bits).parse() 
     nodelist = parser.parse(block_tokens) 
     conditions_nodelists.append((condition, nodelist)) 
     token = parser.next_token() 

    # {% else %} (optional) 
    if token.contents == 'else': 
     nodelist = parser.parse(block_tokens[-1:]) 
     conditions_nodelists.append((None, nodelist)) 
     token = parser.next_token() 

    # {% endif %} 
    assert token.contents == block_tokens[-1] 

    return IfDefNode(defined, conditions_nodelists) 

@register.tag 
def ifdef(parser, token): 
    """Check if variable is defined in the context 

    Unlike the {% if %} tag, this renders the block if the variable(s) 
    exist within the context, not only if they are truthy. That is, variables 
    with None, 0 or [] values would also render the block. 
    """ 
    return _gen_ifdef(parser, token, ('elifdef', 'else', 'endifdef'), True) 

@register.tag 
def ifndef(parser, token): 
    """Check if variable is *not* defined in the context 

    This is the opposite of {% ifdef %}. 
    """ 
    return _gen_ifdef(parser, token, ('elifndef', 'else', 'endifndef'), False) 

तो आप इसे अपने टेम्पलेट में एक {% if %} टैग की तरह का प्रयोग करेंगे:

{% ifdef letters or numbers %} 
    {# do something with letters or numbers #} 
{% else %} 
    {# variables are not defined here #} 
{% endifdef %} 

मुझे यकीन नहीं है कि इसे पूरा करने का एक आसान तरीका है, और जब मैं दृष्टिकोण से बहुत खुश नहीं हूं, तो यह मेरे उपयोग के मामले में अच्छी तरह से काम करता प्रतीत होता है। उम्मीद है की यह मदद करेगा!

+0

धन्यवाद! मुझे लगता है कि यह कई अशुद्ध समाधानों का सबसे साफ है। – sha

0

मुझे यकीन नहीं है कि इस तरह के तर्क टेम्पलेट्स में उपयोग किए जाने चाहिए, तो उन्हें सरल होना चाहिए। (से पहले दृश्य के अंदर, "अगर") जिस तरह से मैं यह बस जोड़ने है का समाधान होगा:

context['letters'] = False #([]/None/False) 
if some_condition = True: 
    ... 
अब

अगर some_condition = False, की तुलना में "के लिए" पाश, टेम्पलेट में नहीं चलेंगे तो आप की जरूरत नहीं है "अगर" अब और।

संबंधित मुद्दे