
from django import template
from django.template.base import token_kwargs
from django.template.loader import get_template
from django.template.loader_tags import BlockNode, ExtendsNode, BlockContext

register = template.Library()

def resolve_blocks(template, context, blocks=None):
    '''Get all the blocks from this template, accounting for 'extends' tags'''
    if blocks is None:
        blocks = BlockContext()

    # If it's just the name, resolve into template
    if isinstance(template, basestring):
        template = get_template(template)

    # Add this templates blocks as the first
    local_blocks = dict(
        (block.name, block)
        for block in template.nodelist.get_nodes_by_type(BlockNode)
    )
    blocks.add_blocks(local_blocks)

    # Do we extend a parent template?
    extends = template.nodelist.get_nodes_by_type(ExtendsNode)
    if extends:
        # Can only have one extends in a template
        extends_node = extends[0]

        # Get the parent, and recurse
        parent_template = extends_node.get_parent(context)
        resolve_blocks(parent_template, context, blocks)

    return blocks


class ContextDict(dict):
    '''Back-port of the ContextDict from Django 1.7'''
    def __init__(self, context, *args, **kwargs):
        super(ContextDict, self).__init__(*args, **kwargs)

        context.dicts.append(self)
        self.context = context

    def __enter__(self):
        return self.context.update(self)

    def __exit__(self, *args, **kwargs):
        self.context.pop()


@register.tag
def form(parser, token):
    '''Prepare to render a Form, using the specified template.

    {% form "template.form" %}
        {% field "blockname" form.somefield ..... %}
        ...
    {% endform %}
    '''
    bits = token.split_contents()
    tag_name = bits.pop(0) # Remove the tag name
    try:
        tmpl_name = parser.compile_filter(bits.pop(0))
    except IndexError:
        raise template.TemplateSyntaxError("%r tag takes at least 1 argument: the widget template" % tag_name)

    kwargs = token_kwargs(bits, parser)

    nodelist = parser.parse(('endform',))
    parser.delete_first_token()

    return FormNode(tmpl_name, nodelist, kwargs)


class FormNode(template.Node):
    def __init__(self, tmpl_name, nodelist, kwargs):
        self.tmpl_name = tmpl_name
        self.nodelist = nodelist
        self.kwargs = kwargs

    def render(self, context):
        # Resolve our arguments
        tmpl_name = self.tmpl_name.resolve(context)
        kwargs = dict(
            (key, val.resolve(context))
            for key, val in self.kwargs.items()
        )

        # Grab the template snippets
        kwargs['formulation'] = resolve_blocks(tmpl_name, context)

        # Render our children
        with ContextDict(context, kwargs) as context:
            return self.nodelist.render(context)


@register.simple_tag(takes_context=True)
def field(context, widget, field, **kwargs):
    field_data = {
        'form_field': field,
        'id': field.auto_id,
    }
    for attr in ('css_classes', 'errors', 'field', 'form',
            'help_text', 'id_for_label', 'label', 'name', 'html_name',
            'value', 'widget',):
        field_data[attr] = getattr(field, attr)
    for attr in ('choices', 'widget',):
        field_data[attr] = getattr(field.field, attr, None)
    kwargs.update(field_data)
    kwargs['block'] = context['formulation'].get_block(widget)
    with ContextDict(context, kwargs) as context:
        return block.render(context)


@register.simple_tag(takes_context=True)
def use(context, widget, **kwargs):
    kwargs['block'] = context['formulation'].get_block(widget)
    with ContextDict(context, kwargs) as context:
        return block.render(context)


@@ -1419,31 +1419,24 @@
 f):%0A        
-return 
 self.context
@@ -1448,16 +1448,44 @@
 te(self)
+%0A        return self.context
 %0A%0A    de
@@ -2872,32 +2872,692 @@
 ender(context)%0A%0A
+def _auto_widget(field):%0A    # Auto-detect%0A    info = %7B%0A        'widget': field.field.widget.__class__.__name__,%0A        'field': field.field.__class__.__name__,%0A        'name': field.name,%0A    %7D%0A%0A    for pattern in (%0A            '%7Bfield%7D_%7Bwidget%7D_%7Bname%7D',%0A            '%7Bfield%7D_%7Bname%7D',%0A            '%7Bwidget%7D_%7Bname%7D',%0A            '%7Bfield%7D_%7Bwidget%7D',%0A            '%7Bname%7D',%0A            '%7Bwidget%7D',%0A            '%7Bfield%7D',%0A        ):%0A        block = context%5B'formulation'%5D.get_block(%0A            pattern.format(info)%0A        )%0A        if block is not None:%0A            return block%0A    raise TemplateSyntaxError(%22Could not find widget for field: %25r%22 %25 field)%0A    %0A
 %0A@register.simpl
@@ -3605,21 +3605,26 @@
 xt, 
-widget, field
+field, widget=None
 , **
@@ -3955,32 +3955,43 @@
 ices', 'widget',
+ 'required'
 ):%0A        field
@@ -4067,16 +4067,76 @@
 d_data)%0A
+    if widget is None:%0A        widget = _auto_widget(field)%0A
     kwar

Add auto-widget detection