Django

Code

Changeset 780

Show
Ignore:
Timestamp:
10/05/05 16:41:41 (3 years ago)
Author:
rjwittams
Message:

Merged to r778. Added template tag decorators:

  • simple_tag : transforms a function outputting a string into a tag.

arguments are converted into tag arguments, and defaults are
supported.

  • inclusion_tag : transforms a function outputting a dictionary into a tag

which renders an included template. The name of the template is
given as an argument to the decorator, and the dictionary
returnd by the function is used to populate the context
to render the included template. The template is loaded at
compile time, and the nodelist cached.

Also made the {%include %} tag load the template at compile time if the argument is a constant string.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/new-admin/django/conf/admin_templates/admin_change_form.html

    r740 r780  
    8888{% if auto_populated_fields %} 
    8989   <script type="text/javascript"> 
    90    {% auto_populated_field_script auto_populated_fields %}  
     90   {% auto_populated_field_script auto_populated_fields change %}  
    9191   </script> 
    9292{% endif %} 
  • django/branches/new-admin/django/conf/global_settings.py

    r712 r780  
    111111 
    112112# Path to the "jing" executable -- needed to validate XMLFields 
    113 JING_PATH = "/usr/bin/jng" 
     113JING_PATH = "/usr/bin/jing" 
    114114 
    115115############## 
  • django/branches/new-admin/django/core/defaulttags.py

    r765 r780  
    228228        return output 
    229229 
     230 
     231class ConstantIncludeNode(template.Node): 
     232    def __init__(self, template_path): 
     233        t = template_loader.get_template(template_path)         
     234        self.nodelist = t.nodelist 
     235 
     236    def render(self, context): 
     237        return self.nodelist.render(context) 
     238 
    230239class IncludeNode(template.Node): 
    231240    def __init__(self, template_path_var): 
     
    632641    if len(bits) != 2: 
    633642        raise template.TemplateSyntaxError, "'include' tag takes one argument: the path to the template to be included" 
     643     
     644    path = bits[1] 
     645    if path[0] in ('"', "'") and path[-1] == path[0]: 
     646        return ConstantIncludeNode(path[1:-1])  
    634647    return IncludeNode(bits[1]) 
    635648 
     
    649662    try: 
    650663        LoadNode.load_taglib(taglib) 
    651     except ImportError
    652         raise template.TemplateSyntaxError, "'%s' is not a valid tag library" % taglib 
     664    except ImportError, e
     665        raise template.TemplateSyntaxError, "'%s' is not a valid tag library, %s" % (taglib, e) 
    653666    return LoadNode(taglib) 
    654667 
  • django/branches/new-admin/django/templatetags/admin_modify.py

    r765 r780  
    66from django.utils.functional import curry 
    77 
     8from django.core.template_decorators import simple_tag, inclusion_tag 
     9 
    810from django.views.admin.main import AdminBoundField 
    911import re 
     
    1416    return '_'.join([ s.lower() for s in word_re.findall(name)[:-1] ]) 
    1517 
    16  
    17 class IncludeAdminScriptNode(template.Node): 
    18     def __init__(self, var): 
    19         self.var = var 
    20   
    21     def render(self, context): 
    22         resolved = template.resolve_variable(self.var, context) 
     18#@simple_tag         
     19def include_admin_script(script_path): 
    2320        return '<script type="text/javascript" src="%s%s"></script>' % \ 
    24             (ADMIN_MEDIA_PREFIX, resolved) 
    25            
    26 class SubmitRowNode(template.Node): 
    27     def __init__(self): 
    28         pass 
    29  
    30     def render(self, context):         
     21            (ADMIN_MEDIA_PREFIX, script_path) 
     22include_admin_script = simple_tag(include_admin_script)           
     23 
     24 
     25#@inclusion_tag('admin_submit_line', takes_context=True) 
     26def submit_row(context):         
    3127        change = context['change'] 
    3228        add = context['add'] 
     
    3733        is_popup = context['is_popup'] 
    3834           
    39          
    40         output = render_to_string('admin_submit_line', { 
     35        return { 
    4136            'onclick_attrib' : (ordered_objects and change  
    4237                                and 'onclick="submitOrderForm();"' or ''),  
     
    4742            'show_save_and_continue': not is_popup, 
    4843            'show_save': True 
    49           }, context); 
    50         context.pop()  
    51         return output; 
    52  
    53 class AdminFieldBoundNode(template.Node): 
    54     def __init__(self, argument): 
    55         self.argument = argument 
    56      
    57     def render(self, context): 
    58         argument_val = template.resolve_variable(self.argument, context) 
    59         if (isinstance(argument_val, list)): 
    60             bound_fields = argument_val  
    61         else: 
    62             bound_fields = [argument_val] 
    63         add = context['add'] 
    64         change = context['change'] 
    65          
    66         context.push() 
    67         context['bound_fields'] = bound_fields 
    68         context['class_names'] = " ".join(self.get_class_names(bound_fields)) 
    69         t = template_loader.get_template("admin_field") 
    70         output =  t.render(context) 
    71         context.pop() 
    72            
    73         return output 
    74  
    75     def get_class_names(self, bound_fields): 
    76  
    77         class_names = ['form-row'] 
    78         for bound_field in bound_fields:  
    79             for f in bound_field.form_fields: 
    80                 if f.errors(): 
    81                     class_names.append('errors') 
    82                     break 
    83            
    84         # Assumes BooleanFields won't be stacked next to each other! 
    85         if isinstance(bound_fields[0].field, meta.BooleanField): 
    86             class_names.append('checkbox-row') 
    87            
    88         return class_names 
    89         
     44        } 
     45 
     46srdec = inclusion_tag('admin_submit_line', takes_context=True) 
     47submit_row = srdec(submit_row) 
     48 
     49#@simple_tag    
     50def field_label(bound_field): 
     51    class_names = [] 
     52    if isinstance(bound_field.field, meta.BooleanField): 
     53        class_names.append("vCheckboxLabel") 
     54    else: 
     55        if not bound_field.field.blank: 
     56            class_names.append('required') 
     57        if not bound_field.first: 
     58            class_names.append('inline') 
     59     
     60    class_str = class_names and ' class="%s"' % ' '.join(class_names) or '' 
     61    return '<label for="%s"%s>%s:</label> ' % \ 
     62            (bound_field.element_id, class_str,  
     63             capfirst(bound_field.field.verbose_name) ) 
     64field_label = simple_tag(field_label) 
     65 
     66 
    9067class FieldWidgetNode(template.Node): 
    9168    def __init__(self, bound_field_var): 
    9269        self.bound_field_var = bound_field_var 
     70        self.nodelists = {} 
     71        t = template_loader.get_template("widget/default") 
     72        self.default = t.nodelist  
    9373 
    9474    def render(self, context): 
     
    10181        context['bound_field'] = bound_field 
    10282        klass = bound_field.field.__class__ 
    103         t = None 
    104         while klass: 
    105             try:  
    106                 field_class_name = klass.__name__ 
    107                 template_name = "widget/%s" % \ 
    108                     class_name_to_underscored(field_class_name) 
    109              
    110                 t = template_loader.get_template(template_name) 
    111                 break 
    112             except template.TemplateDoesNotExist:  
    113                 klass = (len(klass.__bases__) > 0) and klass.__bases__[0] or None 
    114          
    115         if t == None: 
    116             t = template_loader.get_template("widget/default") 
    117         
    118         output = t.render(context) 
     83        if not self.nodelists.has_key(klass): 
     84            t = None 
     85            while klass: 
     86                try:  
     87                    field_class_name = klass.__name__ 
     88                    template_name = "widget/%s" % \ 
     89                        class_name_to_underscored(field_class_name) 
     90                    t = template_loader.get_template(template_name) 
     91                    break 
     92                except template.TemplateDoesNotExist:  
     93                    klass = bool(klass.__bases__) and klass.__bases__[0] or None 
     94              
     95            if t == None: 
     96                nodelist = self.default 
     97            else:            
     98                nodelist = t.nodelist 
     99 
     100            self.nodelists[klass] = nodelist             
     101 
     102        output = self.nodelists[klass].render(context) 
    119103        context.pop() 
    120104        return output 
     
    178162        context['original_row_needed'] = max([fw.use_raw_id_admin() for fw in field_wrapper_list])  
    179163#        context['name_prefix'] = "%s." % (var_name,) 
    180     
    181 class FieldLabelNode(template.Node): 
    182     def __init__(self, bound_field_var): 
    183         self.bound_field_var = bound_field_var 
    184          
    185     def render(self, context): 
    186         bound_field = template.resolve_variable(self.bound_field_var, context) 
    187         class_names = [] 
    188         if isinstance(bound_field.field, meta.BooleanField): 
    189             class_names.append("vCheckboxLabel") 
    190         else: 
    191             if not bound_field.field.blank: 
    192                 class_names.append('required') 
    193             if not bound_field.first: 
    194                 class_names.append('inline') 
    195          
    196         class_str = class_names and ' class="%s"' % ' '.join(class_names) or '' 
    197         return '<label for="%s"%s>%s:</label> ' % (bound_field.element_id, class_str, capfirst(bound_field.field.verbose_name) ) 
    198  
    199 class OutputAllNode(template.Node): 
    200     def __init__(self, form_fields_var): 
    201         self.form_fields_var = form_fields_var 
    202      
    203     def render(self, context): 
    204         form_fields = template.resolve_variable(self.form_fields_var, context) 
    205         return ''.join([str(f) for f in form_fields]) 
    206  
    207 class AutoPopulatedFieldScriptNode(template.Node): 
    208     def __init__(self, auto_pop_var): 
    209         self.auto_pop_var = auto_pop_var 
    210  
    211     def render(self,context): 
    212         auto_pop_fields = template.resolve_variable(self.auto_pop_var, context) 
    213         change = context['change'] 
    214         for field in auto_pop_fields: 
    215             t = [] 
    216             if change: 
    217                 t.append('document.getElementById("id_%s")._changed = true;' % field.name ) 
    218             else:  
    219                 t.append('document.getElementById("id_%s").onchange = function() { this._changed = true; };' % field.name) 
    220  
    221             add_values = ' + " " + '.join(['document.getElementById("id_%s").value' % g for g in field.prepopulate_from]) 
    222             for f in field.prepopulate_from: 
    223                 t.append('document.getElementById("id_%s").onkeyup = function() { var e = document.getElementById("id_%s"); if(e._changed) { e.value = URLify(%s, %s);} } ' % (f, field.name, add_values, field.maxlength) ) 
    224  
    225         return ''.join(t) 
    226  
    227 class FilterInterfaceScriptMaybeNode(template.Node): 
    228     def __init__(self, bound_field_var): 
    229        self.bound_field_var = bound_field_var 
    230  
    231     def render(self, context): 
    232         bound_field = template.resolve_variable(self.bound_field_var, context) 
    233         f = bound_field.field  
    234         if f.rel and isinstance(f.rel, meta.ManyToMany) and f.rel.filter_interface: 
    235            return '<script type="text/javascript">addEvent(window, "load", function(e) { SelectFilter.init("id_%s", "%s", %s, %r); });</script>\n' % (f.name, f.verbose_name, f.rel.filter_interface-1, ADMIN_MEDIA_PREFIX)  
     164 
     165 
     166#@simple_tag 
     167def output_all(form_fields): 
     168    return ''.join([str(f) for f in form_fields]) 
     169output_all = simple_tag(output_all) 
     170 
     171 
     172#@simple_tag 
     173def auto_populated_field_script(auto_pop_fields, change = False): 
     174    for field in auto_pop_fields: 
     175        t = [] 
     176        if change: 
     177            t.append('document.getElementById("id_%s")._changed = true;' % field.name ) 
    236178        else:  
    237             return '' 
    238  
    239       
    240  
    241  
    242 def do_submit_row(parser, token): 
    243     return SubmitRowNode() 
    244  
     179            t.append('document.getElementById("id_%s").onchange = function() { this._changed = true; };' % field.name) 
     180 
     181        add_values = ' + " " + '.join(['document.getElementById("id_%s").value' % g for g in field.prepopulate_from]) 
     182        for f in field.prepopulate_from: 
     183            t.append('document.getElementById("id_%s").onkeyup = function() { var e = document.getElementById("id_%s"); if(e._changed) { e.value = URLify(%s, %s);} } ' % (f, field.name, add_values, field.maxlength) ) 
     184 
     185    return ''.join(t) 
     186auto_populated_field_script = simple_tag(auto_populated_field_script) 
     187 
     188#@simple_tag 
     189def filter_interface_script_maybe(bound_field): 
     190    f = bound_field.field  
     191    if f.rel and isinstance(f.rel, meta.ManyToMany) and f.rel.filter_interface: 
     192       return '<script type="text/javascript">addEvent(window, "load", function(e) { SelectFilter.init("id_%s", "%s", %s, %r); });</script>\n' % (f.name, f.verbose_name, f.rel.filter_interface-1, ADMIN_MEDIA_PREFIX)  
     193    else:  
     194        return '' 
     195filter_interface_script_maybe = simple_tag(filter_interface_script_maybe) 
    245196 
    246197def do_one_arg_tag(node_factory, parser,token): 
     
    252203 
    253204one_arg_tag_nodes = [ 
    254     IncludeAdminScriptNode, 
    255     AdminFieldBoundNode, 
    256     FieldLabelNode, 
    257205    FieldWidgetNode,  
    258     OutputAllNode, 
    259206    EditInlineNode,  
    260     AutoPopulatedFieldScriptNode, 
    261     FilterInterfaceScriptMaybeNode, 
    262207] 
    263208 
     
    268213    template.register_tag(tag_name, parse_func) 
    269214 
    270   
    271  
    272215for node in one_arg_tag_nodes: 
    273216    register_one_arg_tag(node)     
    274217 
    275 template.register_tag('submit_row', do_submit_row ) 
     218      
     219#@inclusion_tag('admin_field', takes_context=True) 
     220def admin_field_bound(context, argument_val): 
     221    if (isinstance(argument_val, list)): 
     222        bound_fields = argument_val  
     223    else: 
     224        bound_fields = [argument_val] 
     225    add = context['add'] 
     226    change = context['change'] 
     227    
     228    class_names = ['form-row'] 
     229    for bound_field in bound_fields:  
     230        for f in bound_field.form_fields: 
     231            if f.errors(): 
     232                class_names.append('errors') 
     233                break 
     234       
     235    # Assumes BooleanFields won't be stacked next to each other! 
     236    if isinstance(bound_fields[0].field, meta.BooleanField): 
     237        class_names.append('checkbox-row') 
     238 
     239    return {  
     240        'add' : context['add'], 
     241        'change' : context['change'], 
     242        'bound_fields' :  bound_fields,  
     243        'class_names' : " ".join(class_names) 
     244    }  
     245 
     246     
     247afbdec = inclusion_tag('admin_field', takes_context=True)     
     248admin_field_bound = afbdec(admin_field_bound) 
     249 
     250