Ticket #4565: template-iter-render-r3369.patch

File template-iter-render-r3369.patch, 38.3 KB (added by (removed), 17 years ago)
  • django/contrib/admin/templatetags/admin_modify.py

    === modified file 'django/contrib/admin/templatetags/admin_modify.py'
     
    9494            return cls.nodelists[klass]
    9595    get_nodelist = classmethod(get_nodelist)
    9696
    97     def render(self, context):
     97    def iter_render(self, context):
    9898        bound_field = template.resolve_variable(self.bound_field_var, context)
    9999
    100100        context.push()
    101101        context['bound_field'] = bound_field
    102102
    103         output = self.get_nodelist(bound_field.field.__class__).render(context)
     103        for chunk in self.get_nodelist(bound_field.field.__class__).iter_render(context):
     104            yield chunk
    104105        context.pop()
    105         return output
    106106
    107107class FieldWrapper(object):
    108108    def __init__(self, field ):
     
    157157    def __init__(self, rel_var):
    158158        self.rel_var = rel_var
    159159
    160     def render(self, context):
     160    def iter_render(self, context):
    161161        relation = template.resolve_variable(self.rel_var, context)
    162162        context.push()
    163163        if relation.field.rel.edit_inline == models.TABULAR:
     
    169169        original = context.get('original', None)
    170170        bound_related_object = relation.bind(context['form'], original, bound_related_object_class)
    171171        context['bound_related_object'] = bound_related_object
    172         t = loader.get_template(bound_related_object.template_name())
    173         output = t.render(context)
     172        for chunk in loader.get_template(bound_related_object.template_name()).iter_render(context):
     173            yield chunk
    174174        context.pop()
    175         return output
    176175
    177176def output_all(form_fields):
    178177    return ''.join([str(f) for f in form_fields])
  • django/contrib/admin/templatetags/adminapplist.py

    === modified file 'django/contrib/admin/templatetags/adminapplist.py'
     
    77    def __init__(self, varname):
    88        self.varname = varname
    99
    10     def render(self, context):
     10    def iter_render(self, context):
    1111        from django.db import models
    1212        from django.utils.text import capfirst
    1313        app_list = []
     
    5454                        'models': model_list,
    5555                    })
    5656        context[self.varname] = app_list
    57         return ''
     57        return ()
    5858
    5959def get_admin_app_list(parser, token):
    6060    """
  • django/contrib/admin/templatetags/log.py

    === modified file 'django/contrib/admin/templatetags/log.py'
     
    1010    def __repr__(self):
    1111        return "<GetAdminLog Node>"
    1212
    13     def render(self, context):
     13    def iter_render(self, context):
    1414        if self.user is None:
    1515            context[self.varname] = LogEntry.objects.all().select_related()[:self.limit]
    1616        else:
    1717            if not self.user.isdigit():
    1818                self.user = context[self.user].id
    1919            context[self.varname] = LogEntry.objects.filter(user__id__exact=self.user).select_related()[:self.limit]
    20         return ''
     20        return ()
    2121
    2222class DoGetAdminLog:
    2323    """
  • django/contrib/comments/templatetags/comments.py

    === modified file 'django/contrib/comments/templatetags/comments.py'
     
    2424        self.photo_options, self.rating_options = photo_options, rating_options
    2525        self.is_public = is_public
    2626
    27     def render(self, context):
     27    def iter_render(self, context):
    2828        from django.conf import settings
    2929        from django.utils.text import normalize_newlines
    3030        import base64
     
    3333            try:
    3434                self.obj_id = template.resolve_variable(self.obj_id_lookup_var, context)
    3535            except template.VariableDoesNotExist:
    36                 return ''
     36                return
    3737            # Validate that this object ID is valid for this content-type.
    3838            # We only have to do this validation if obj_id_lookup_var is provided,
    3939            # because do_comment_form() validates hard-coded object IDs.
     
    6767            context['hash'] = Comment.objects.get_security_hash(context['options'], context['photo_options'], context['rating_options'], context['target'])
    6868            context['logout_url'] = settings.LOGOUT_URL
    6969            default_form = loader.get_template(COMMENT_FORM)
    70         output = default_form.render(context)
     70        for chunk in default_form.iter_render(context):
     71            yield chunk
    7172        context.pop()
    72         return output
    7373
    7474class CommentCountNode(template.Node):
    7575    def __init__(self, package, module, context_var_name, obj_id, var_name, free):
     
    7777        self.context_var_name, self.obj_id = context_var_name, obj_id
    7878        self.var_name, self.free = var_name, free
    7979
    80     def render(self, context):
     80    def iter_render(self, context):
    8181        from django.conf import settings
    8282        manager = self.free and FreeComment.objects or Comment.objects
    8383        if self.context_var_name is not None:
     
    8686            content_type__app_label__exact=self.package,
    8787            content_type__model__exact=self.module, site__id__exact=settings.SITE_ID).count()
    8888        context[self.var_name] = comment_count
    89         return ''
     89        return ()
    9090
    9191class CommentListNode(template.Node):
    9292    def __init__(self, package, module, context_var_name, obj_id, var_name, free, ordering, extra_kwargs=None):
     
    9696        self.ordering = ordering
    9797        self.extra_kwargs = extra_kwargs or {}
    9898
    99     def render(self, context):
     99    def iter_render(self, context):
    100100        from django.conf import settings
    101101        get_list_function = self.free and FreeComment.objects.filter or Comment.objects.get_list_with_karma
    102102        if self.context_var_name is not None:
    103103            try:
    104104                self.obj_id = template.resolve_variable(self.context_var_name, context)
    105105            except template.VariableDoesNotExist:
    106                 return ''
     106                return ()
    107107        kwargs = {
    108108            'object_id__exact': self.obj_id,
    109109            'content_type__app_label__exact': self.package,
     
    127127                comment_list = [c for c in comment_list if not c.is_hidden or (user_id == c.user_id)]
    128128
    129129        context[self.var_name] = comment_list
    130         return ''
     130        return ()
    131131
    132132class DoCommentForm:
    133133    """
  • django/core/servers/basehttp.py

    === modified file 'django/core/servers/basehttp.py'
     
    309309        """
    310310        if not self.result_is_file() and not self.sendfile():
    311311            for data in self.result:
    312                 self.write(data)
     312                self.write(data, False)
    313313            self.finish_content()
    314314        self.close()
    315315
     
    377377        else:
    378378            self._write('Status: %s\r\n' % self.status)
    379379
    380     def write(self, data):
     380    def write(self, data, flush=True):
    381381        """'write()' callable as specified by PEP 333"""
    382382
    383383        assert type(data) is StringType,"write() argument must be string"
     
    394394
    395395        # XXX check Content-Length and truncate if too many bytes written?
    396396        self._write(data)
    397         self._flush()
     397        if flush:
     398            self._flush()
    398399
    399400    def sendfile(self):
    400401        """Platform-specific file transmission
     
    421422        if not self.headers_sent:
    422423            self.headers['Content-Length'] = "0"
    423424            self.send_headers()
    424         else:
    425             pass # XXX check if content-length was too short?
    426425
    427426    def close(self):
    428427        try:
  • django/http/__init__.py

    === modified file 'django/http/__init__.py'
     
    231231    content = property(_get_content, _set_content)
    232232
    233233    def __iter__(self):
    234         self._iterator = self._container.__iter__()
    235         return self
    236 
    237     def next(self):
    238         chunk = self._iterator.next()
    239         if isinstance(chunk, unicode):
    240             chunk = chunk.encode(self._charset)
    241         return chunk
     234        for chunk in self._container:
     235            if isinstance(chunk, unicode):
     236                chunk = chunk.encode(self._charset)
     237            yield chunk
    242238
    243239    def close(self):
    244240        if hasattr(self._container, 'close'):
  • django/oldforms/__init__.py

    === modified file 'django/oldforms/__init__.py'
     
    309309        return data
    310310    html2python = staticmethod(html2python)
    311311
     312    def iter_render(self, data):
     313        # this even needed?
     314        return (self.render(data),)
     315
    312316    def render(self, data):
    313317        raise NotImplementedError
    314318
  • django/shortcuts/__init__.py

    === modified file 'django/shortcuts/__init__.py'
     
    77from django.db.models.manager import Manager
    88
    99def render_to_response(*args, **kwargs):
    10     return HttpResponse(loader.render_to_string(*args, **kwargs))
     10    return HttpResponse(loader.render_to_iter(*args, **kwargs))
    1111load_and_render = render_to_response # For backwards compatibility.
    1212
    1313def get_object_or_404(klass, *args, **kwargs):
  • django/template/__init__.py

    === modified file 'django/template/__init__.py'
     
    167167            for subnode in node:
    168168                yield subnode
    169169
    170     def render(self, context):
     170    def iter_render(self, context):
    171171        "Display stage -- can be called many times"
    172         return self.nodelist.render(context)
     172        return self.nodelist.iter_render(context)
     173   
     174    def render(self, context):
     175        return ''.join(self.iter_render(context))
    173176
    174177def compile_string(template_string, origin):
    175178    "Compiles template_string into NodeList ready for rendering"
     
    699702    return current
    700703
    701704class Node(object):
     705    def iter_render(self, context):
     706        return (self.render(context),)
     707
    702708    def render(self, context):
    703709        "Return the node rendered as a string"
    704         pass
     710        return ''.join(self.iter_render(context))
    705711
    706712    def __iter__(self):
    707713        yield self
     
    716722        return nodes
    717723
    718724class NodeList(list):
     725
    719726    def render(self, context):
    720         bits = []
     727        return ''.join(self.iter_render(context))
     728
     729    def iter_render(self, context):
    721730        for node in self:
    722             if isinstance(node, Node):
    723                 bits.append(self.render_node(node, context))
    724             else:
    725                 bits.append(node)
    726         return ''.join(bits)
     731            for chunk in node.iter_render(context):
     732                yield chunk
    727733
    728734    def get_nodes_by_type(self, nodetype):
    729735        "Return a list of all nodes of the given type"
     
    732738            nodes.extend(node.get_nodes_by_type(nodetype))
    733739        return nodes
    734740
    735     def render_node(self, node, context):
    736         return(node.render(context))
    737741
    738742class DebugNodeList(NodeList):
    739     def render_node(self, node, context):
    740         try:
    741             result = node.render(context)
    742         except TemplateSyntaxError, e:
    743             if not hasattr(e, 'source'):
    744                 e.source = node.source
    745             raise
    746         except Exception, e:
    747             from sys import exc_info
    748             wrapped = TemplateSyntaxError('Caught an exception while rendering: %s' % e)
    749             wrapped.source = node.source
    750             wrapped.exc_info = exc_info()
    751             raise wrapped
    752         return result
     743
     744    def iter_render(self, node, context):
     745        for node in self:
     746            if not isinstance(node, Node):
     747                yield node
     748                continue
     749            try:
     750                for chunk in node.iter_render(context):
     751                    yield chunk
     752            except TemplateSyntaxError, e:
     753                if not hasattr(e, 'source'):
     754                    e.source = node.source
     755                raise
     756            except Exception, e:
     757                from sys import exc_info
     758                wrapped = TemplateSyntaxError('Caught an exception while rendering: %s' % e)
     759                wrapped.source = node.source
     760                wrapped.exc_info = exc_info()
     761                raise wrapped
    753762
    754763class TextNode(Node):
    755764    def __init__(self, s):
     
    758767    def __repr__(self):
    759768        return "<Text Node: '%s'>" % self.s[:25]
    760769
     770    def iter_render(self, context):
     771        return (self.s,)
     772
    761773    def render(self, context):
    762774        return self.s
    763775
     
    781793        else:
    782794            return output
    783795
     796    def iter_render(self, context):
     797        return (self.render(context),)
     798
    784799    def render(self, context):
    785800        output = self.filter_expression.resolve(context)
    786801        return self.encode_output(output)
    787802
    788803class DebugVariableNode(VariableNode):
     804
    789805    def render(self, context):
    790806        try:
    791807            output = self.filter_expression.resolve(context)
     
    869885            def __init__(self, vars_to_resolve):
    870886                self.vars_to_resolve = vars_to_resolve
    871887
     888            def iter_render(self, context):
     889                return (self.render(context),)
     890
    872891            def render(self, context):
    873892                resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve]
    874893                return func(*resolved_vars)
     
    891910                def __init__(self, vars_to_resolve):
    892911                    self.vars_to_resolve = vars_to_resolve
    893912
    894                 def render(self, context):
     913                def iter_render(self, context):
    895914                    resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve]
    896915                    if takes_context:
    897916                        args = [context] + resolved_vars
     
    907926                        else:
    908927                            t = get_template(file_name)
    909928                        self.nodelist = t.nodelist
    910                     return self.nodelist.render(context_class(dict))
     929                    return self.nodelist.iter_render(context_class(dict))
    911930
    912931            compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, InclusionNode)
    913932            compile_func.__doc__ = func.__doc__
  • django/template/defaulttags.py

    === modified file 'django/template/defaulttags.py'
     
    1414        for index in xrange(len(data)-1, -1, -1):
    1515            yield data[index]
    1616
    17 
    1817register = Library()
    1918
    2019class CommentNode(Node):
    21     def render(self, context):
    22         return ''
     20    def iter_render(self, context):
     21        return ()
    2322
    2423class CycleNode(Node):
    2524    def __init__(self, cyclevars, variable_name=None):
     
    2827        self.counter = -1
    2928        self.variable_name = variable_name
    3029
     30    def iter_render(self, context):
     31        return (self.render(context),)
     32
    3133    def render(self, context):
    3234        self.counter += 1
    3335        value = self.cyclevars[self.counter % self.cyclevars_len]
     
    3638        return value
    3739
    3840class DebugNode(Node):
    39     def render(self, context):
     41    def iter_render(self, context):
    4042        from pprint import pformat
    41         output = [pformat(val) for val in context]
    42         output.append('\n\n')
    43         output.append(pformat(sys.modules))
    44         return ''.join(output)
     43        for val in context:
     44            yield pformat(val)
     45        yield "\n\n"
     46        yield pformat(sys.modules)
    4547
    4648class FilterNode(Node):
    4749    def __init__(self, filter_expr, nodelist):
    4850        self.filter_expr, self.nodelist = filter_expr, nodelist
    4951
    50     def render(self, context):
     52    def iter_render(self, context):
    5153        output = self.nodelist.render(context)
    5254        # apply filters
    5355        context.update({'var': output})
    5456        filtered = self.filter_expr.resolve(context)
    5557        context.pop()
    56         return filtered
     58        return (filtered,)
    5759
    5860class FirstOfNode(Node):
    5961    def __init__(self, vars):
    6062        self.vars = vars
    6163
     64    def iter_render(self, context):
     65        return (self.render(context),)
     66
    6267    def render(self, context):
    6368        for var in self.vars:
    6469            try:
     
    9499        nodes.extend(self.nodelist_loop.get_nodes_by_type(nodetype))
    95100        return nodes
    96101
    97     def render(self, context):
    98         nodelist = NodeList()
     102    def iter_render(self, context):
    99103        if 'forloop' in context:
    100104            parentloop = context['forloop']
    101105        else:
     
    103107        context.push()
    104108        try:
    105109            values = self.sequence.resolve(context, True)
     110            if values is None:
     111                values = ()
     112            elif not hasattr(values, '__len__'):
     113                values = list(values)
    106114        except VariableDoesNotExist:
    107             values = []
    108         if values is None:
    109             values = []
    110         if not hasattr(values, '__len__'):
    111             values = list(values)
     115            values = ()
    112116        len_values = len(values)
    113117        if self.reversed:
    114118            values = reversed(values)
     
    131135                context.update(dict(zip(self.loopvars, item)))
    132136            else:
    133137                context[self.loopvars[0]] = item
     138            # we inline this to avoid the overhead since fornode is pretty common.
    134139            for node in self.nodelist_loop:
    135                 nodelist.append(node.render(context))
     140                for chunk in node.iter_render(context):
     141                    yield chunk
    136142            if unpack:
    137143                # The loop variables were pushed on to the context so pop them
    138144                # off again. This is necessary because the tag lets the length
     
    141147                # context.
    142148                context.pop()
    143149        context.pop()
    144         return nodelist.render(context)
    145150
    146151class IfChangedNode(Node):
    147152    def __init__(self, nodelist, *varlist):
     
    149154        self._last_seen = None
    150155        self._varlist = varlist
    151156
    152     def render(self, context):
     157    def iter_render(self, context):
    153158        if 'forloop' in context and context['forloop']['first']:
    154159            self._last_seen = None
    155160        try:
     
    167172            self._last_seen = compare_to
    168173            context.push()
    169174            context['ifchanged'] = {'firstloop': firstloop}
    170             content = self.nodelist.render(context)
     175            for chunk in self.nodelist.iter_render(context):
     176                yield chunk
    171177            context.pop()
    172             return content
    173         else:
    174             return ''
    175178
    176179class IfEqualNode(Node):
    177180    def __init__(self, var1, var2, nodelist_true, nodelist_false, negate):
     
    182185    def __repr__(self):
    183186        return "<IfEqualNode>"
    184187
    185     def render(self, context):
     188    def iter_render(self, context):
    186189        try:
    187190            val1 = resolve_variable(self.var1, context)
    188191        except VariableDoesNotExist:
     
    192195        except VariableDoesNotExist:
    193196            val2 = None
    194197        if (self.negate and val1 != val2) or (not self.negate and val1 == val2):
    195             return self.nodelist_true.render(context)
    196         return self.nodelist_false.render(context)
     198            return self.nodelist_true.iter_render(context)
     199        return self.nodelist_false.iter_render(context)
    197200
    198201class IfNode(Node):
    199202    def __init__(self, bool_exprs, nodelist_true, nodelist_false, link_type):
     
    218221        nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype))
    219222        return nodes
    220223
    221     def render(self, context):
     224    def iter_render(self, context):
    222225        if self.link_type == IfNode.LinkTypes.or_:
    223226            for ifnot, bool_expr in self.bool_exprs:
    224227                try:
     
    226229                except VariableDoesNotExist:
    227230                    value = None
    228231                if (value and not ifnot) or (ifnot and not value):
    229                     return self.nodelist_true.render(context)
    230             return self.nodelist_false.render(context)
     232                    return self.nodelist_true.iter_render(context)
     233            return self.nodelist_false.iter_render(context)
    231234        else:
    232235            for ifnot, bool_expr in self.bool_exprs:
    233236                try:
     
    235238                except VariableDoesNotExist:
    236239                    value = None
    237240                if not ((value and not ifnot) or (ifnot and not value)):
    238                     return self.nodelist_false.render(context)
    239             return self.nodelist_true.render(context)
     241                    return self.nodelist_false.iter_render(context)
     242            return self.nodelist_true.iter_render(context)
    240243
    241244    class LinkTypes:
    242245        and_ = 0,
     
    247250        self.target, self.expression = target, expression
    248251        self.var_name = var_name
    249252
    250     def render(self, context):
     253    def iter_render(self, context):
    251254        obj_list = self.target.resolve(context, True)
    252255        if obj_list == None: # target_var wasn't found in context; fail silently
    253256            context[self.var_name] = []
    254             return ''
     257            return ()
    255258        output = [] # list of dictionaries in the format {'grouper': 'key', 'list': [list of contents]}
    256259        for obj in obj_list:
    257260            grouper = self.expression.resolve(obj, True)
     
    261264            else:
    262265                output.append({'grouper': grouper, 'list': [obj]})
    263266        context[self.var_name] = output
    264         return ''
     267        return ()
    265268
    266269def include_is_allowed(filepath):
    267270    for root in settings.ALLOWED_INCLUDE_ROOTS:
     
    273276    def __init__(self, filepath, parsed):
    274277        self.filepath, self.parsed = filepath, parsed
    275278
    276     def render(self, context):
     279    def iter_render(self, context):
    277280        if not include_is_allowed(self.filepath):
    278281            if settings.DEBUG:
    279                 return "[Didn't have permission to include file]"
     282                return ("[Didn't have permission to include file]",)
    280283            else:
    281284                return '' # Fail silently for invalid includes.
    282285        try:
     
    287290            output = ''
    288291        if self.parsed:
    289292            try:
    290                 t = Template(output, name=self.filepath)
    291                 return t.render(context)
     293                return Template(output, name=self.filepath).iter_render(context)
    292294            except TemplateSyntaxError, e:
    293295                if settings.DEBUG:
    294296                    return "[Included template had syntax error: %s]" % e
    295297                else:
    296298                    return '' # Fail silently for invalid included templates.
    297         return output
     299        return (output,)
    298300
    299301class LoadNode(Node):
    300     def render(self, context):
    301         return ''
     302    def iter_render(self, context):
     303        return ()
    302304
    303305class NowNode(Node):
    304306    def __init__(self, format_string):
    305307        self.format_string = format_string
    306308
     309    def iter_render(self, context):
     310        return (self.render(context),)
     311
    307312    def render(self, context):
    308313        from datetime import datetime
    309314        from django.utils.dateformat import DateFormat
     
    332337    def __init__(self, tagtype):
    333338        self.tagtype = tagtype
    334339
     340    def iter_render(self, context):
     341        return (self.render(context),)
     342
    335343    def render(self, context):
    336344        return self.mapping.get(self.tagtype, '')
    337345
     
    341349        self.args = args
    342350        self.kwargs = kwargs
    343351
    344     def render(self, context):
     352    def iter_render(self, context):
    345353        from django.core.urlresolvers import reverse, NoReverseMatch
    346354        args = [arg.resolve(context) for arg in self.args]
    347355        kwargs = dict([(k, v.resolve(context)) for k, v in self.kwargs.items()])
    348356        try:
    349             return reverse(self.view_name, args=args, kwargs=kwargs)
     357            return (reverse(self.view_name, args=args, kwargs=kwargs),)
    350358        except NoReverseMatch:
    351359            try:
    352360                project_name = settings.SETTINGS_MODULE.split('.')[0]
    353361                return reverse(project_name + '.' + self.view_name, args=args, kwargs=kwargs)
    354362            except NoReverseMatch:
    355                 return ''
     363                return ()
    356364
    357365class WidthRatioNode(Node):
    358366    def __init__(self, val_expr, max_expr, max_width):
     
    360368        self.max_expr = max_expr
    361369        self.max_width = max_width
    362370
     371    def iter_render(self, context):
     372        return (self.render(context),)
     373
    363374    def render(self, context):
    364375        try:
    365376            value = self.val_expr.resolve(context)
     
    383394    def __repr__(self):
    384395        return "<WithNode>"
    385396
    386     def render(self, context):
     397    def iter_render(self, context):
    387398        val = self.var.resolve(context)
    388399        context.push()
    389400        context[self.name] = val
    390         output = self.nodelist.render(context)
     401        for chunk in self.nodelist.iter_render(context):
     402            yield chunk
    391403        context.pop()
    392         return output
    393404
    394405#@register.tag
    395406def comment(parser, token):
  • django/template/loader.py

    === modified file 'django/template/loader.py'
     
    8787    """
    8888    return Template(source, origin, name)
    8989
    90 def render_to_string(template_name, dictionary=None, context_instance=None):
    91     """
    92     Loads the given template_name and renders it with the given dictionary as
    93     context. The template_name may be a string to load a single template using
    94     get_template, or it may be a tuple to use select_template to find one of
    95     the templates in the list. Returns a string.
    96     """
    97     dictionary = dictionary or {}
     90def _render_setup(template_name, dictionary=None, context_instance=None):
     91    """
     92    common setup code for render_to_string and render_to_iter
     93    """
     94    if dictionary is None:
     95        dictionary = {}
    9896    if isinstance(template_name, (list, tuple)):
    9997        t = select_template(template_name)
    10098    else:
     
    103101        context_instance.update(dictionary)
    104102    else:
    105103        context_instance = Context(dictionary)
    106     return t.render(context_instance)
     104    return t, context_instance
     105
     106def render_to_string(template_name, dictionary=None, context_instance=None):
     107    """
     108    Loads the given template_name and renders it with the given dictionary as
     109    context. The template_name may be a string to load a single template using
     110    get_template, or it may be a tuple to use select_template to find one of
     111    the templates in the list. Returns a string.
     112    """
     113    t, c = _render_setup(template_name, dictionary=dictionary, context_instance=context_instance)
     114    return t.render(c)
     115
     116def render_to_iter(template_name, dictionary=None, context_instance=None):
     117    """
     118    Loads the given template_name and renders it with the given dictionary as
     119    context. The template_name may be a string to load a single template using
     120    get_template, or it may be a tuple to use select_template to find one of
     121    the templates in the list. Returns a string.
     122    """
     123    t, c = _render_setup(template_name, dictionary=dictionary, context_instance=context_instance)
     124    return t.iter_render(c)
     125
    107126
    108127def select_template(template_name_list):
    109128    "Given a list of template names, returns the first that can be loaded."
  • django/template/loader_tags.py

    === modified file 'django/template/loader_tags.py'
     
    1515    def __repr__(self):
    1616        return "<Block Node: %s. Contents: %r>" % (self.name, self.nodelist)
    1717
    18     def render(self, context):
     18    def iter_render(self, context):
    1919        context.push()
    2020        # Save context in case of block.super().
    2121        self.context = context
    2222        context['block'] = self
    23         result = self.nodelist.render(context)
     23        for chunk in self.nodelist.iter_render(context):
     24            yield chunk
    2425        context.pop()
    25         return result
    2626
    2727    def super(self):
    2828        if self.parent:
     
    5959        else:
    6060            return get_template_from_string(source, origin, parent)
    6161
    62     def render(self, context):
     62    def iter_render(self, context):
    6363        compiled_parent = self.get_parent(context)
    6464        parent_is_child = isinstance(compiled_parent.nodelist[0], ExtendsNode)
    6565        parent_blocks = dict([(n.name, n) for n in compiled_parent.nodelist.get_nodes_by_type(BlockNode)])
     
    7979                parent_block.parent = block_node.parent
    8080                parent_block.add_parent(parent_block.nodelist)
    8181                parent_block.nodelist = block_node.nodelist
    82         return compiled_parent.render(context)
     82        return compiled_parent.iter_render(context)
    8383
    8484class ConstantIncludeNode(Node):
    8585    def __init__(self, template_path):
     
    9191                raise
    9292            self.template = None
    9393
    94     def render(self, context):
     94    def iter_render(self, context):
    9595        if self.template:
    96             return self.template.render(context)
    97         else:
    98             return ''
     96            return self.template.iter_render(context)
     97        return ()
    9998
    10099class IncludeNode(Node):
    101100    def __init__(self, template_name):
    102101        self.template_name = template_name
    103102
    104     def render(self, context):
     103    def iter_render(self, context):
    105104        try:
    106105            template_name = resolve_variable(self.template_name, context)
    107106            t = get_template(template_name)
    108             return t.render(context)
     107            return t.iter_render(context)
    109108        except TemplateSyntaxError, e:
    110109            if settings.TEMPLATE_DEBUG:
    111110                raise
    112             return ''
     111            return ()
    113112        except:
    114             return '' # Fail silently for invalid included templates.
     113            return () # Fail silently for invalid included templates.
    115114
    116115def do_block(parser, token):
    117116    """
  • django/test/utils.py

    === modified file 'django/test/utils.py'
     
    1717    """
    1818    dispatcher.send(signal=signals.template_rendered, sender=self, template=self, context=context)
    1919    return self.nodelist.render(context)
     20
     21def instrumented_test_iter_render(self, context):
     22    """An instrumented Template iter_render method, providing a signal
     23    that can be intercepted by the test system Client
     24   
     25    """
     26    for chunk in self.nodelist.iter_render(context):
     27        yield chunk
     28    dispatcher.send(signal=signals.template_rendered, sender=self, template=self, context=context)
    2029   
    2130class TestSMTPConnection(object):
    2231    """A substitute SMTP connection for use during test sessions.
     
    4453       
    4554    """
    4655    Template.original_render = Template.render
     56    Template.original_iter_render = Template.iter_render
    4757    Template.render = instrumented_test_render
     58    Template.iter_render = instrumented_test_render
    4859   
    4960    mail.original_SMTPConnection = mail.SMTPConnection
    5061    mail.SMTPConnection = TestSMTPConnection
     
    5970       
    6071    """
    6172    Template.render = Template.original_render
    62     del Template.original_render
     73    Template.iter_render = Template.original_iter_render
     74    del Template.original_render, Template.original_iter_render
    6375   
    6476    mail.SMTPConnection = mail.original_SMTPConnection
    6577    del mail.original_SMTPConnection
  • django/views/debug.py

    === modified file 'django/views/debug.py'
     
    137137        'template_does_not_exist': template_does_not_exist,
    138138        'loader_debug_info': loader_debug_info,
    139139    })
    140     return HttpResponseServerError(t.render(c), mimetype='text/html')
     140    return HttpResponseServerError(t.iter_render(c), mimetype='text/html')
    141141
    142142def technical_404_response(request, exception):
    143143    "Create a technical 404 error response. The exception should be the Http404."
     
    160160        'request_protocol': request.is_secure() and "https" or "http",
    161161        'settings': get_safe_settings(),
    162162    })
    163     return HttpResponseNotFound(t.render(c), mimetype='text/html')
     163    return HttpResponseNotFound(t.iter_render(c), mimetype='text/html')
    164164
    165165def empty_urlconf(request):
    166166    "Create an empty URLconf 404 error response."
     
    168168    c = Context({
    169169        'project_name': settings.SETTINGS_MODULE.split('.')[0]
    170170    })
    171     return HttpResponseNotFound(t.render(c), mimetype='text/html')
     171    return HttpResponseNotFound(t.iter_render(c), mimetype='text/html')
    172172
    173173def _get_lines_from_file(filename, lineno, context_lines, loader=None, module_name=None):
    174174    """
  • django/views/defaults.py

    === modified file 'django/views/defaults.py'
     
    7676            The path of the requested URL (e.g., '/app/pages/bad_page/')
    7777    """
    7878    t = loader.get_template(template_name) # You need to create a 404.html template.
    79     return http.HttpResponseNotFound(t.render(RequestContext(request, {'request_path': request.path})))
     79    return http.HttpResponseNotFound(t.iter_render(RequestContext(request, {'request_path': request.path})))
    8080
    8181def server_error(request, template_name='500.html'):
    8282    """
     
    8686    Context: None
    8787    """
    8888    t = loader.get_template(template_name) # You need to create a 500.html template.
    89     return http.HttpResponseServerError(t.render(Context({})))
     89    return http.HttpResponseServerError(t.iter_render(Context({})))
  • django/views/generic/create_update.py

    === modified file 'django/views/generic/create_update.py'
     
    6868            c[key] = value()
    6969        else:
    7070            c[key] = value
    71     return HttpResponse(t.render(c))
     71    return HttpResponse(t.iter_render(c))
    7272
    7373def update_object(request, model, object_id=None, slug=None,
    7474        slug_field=None, template_name=None, template_loader=loader,
     
    141141            c[key] = value()
    142142        else:
    143143            c[key] = value
    144     response = HttpResponse(t.render(c))
     144    response = HttpResponse(t.iter_render(c))
    145145    populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname))
    146146    return response
    147147
     
    195195                c[key] = value()
    196196            else:
    197197                c[key] = value
    198         response = HttpResponse(t.render(c))
     198        response = HttpResponse(t.iter_render(c))
    199199        populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname))
    200200        return response
  • django/views/generic/date_based.py

    === modified file 'django/views/generic/date_based.py'
     
    4444            c[key] = value()
    4545        else:
    4646            c[key] = value
    47     return HttpResponse(t.render(c), mimetype=mimetype)
     47    return HttpResponse(t.iter_render(c), mimetype=mimetype)
    4848
    4949def archive_year(request, year, queryset, date_field, template_name=None,
    5050        template_loader=loader, extra_context=None, allow_empty=False,
     
    9292            c[key] = value()
    9393        else:
    9494            c[key] = value
    95     return HttpResponse(t.render(c), mimetype=mimetype)
     95    return HttpResponse(t.iter_render(c), mimetype=mimetype)
    9696
    9797def archive_month(request, year, month, queryset, date_field,
    9898        month_format='%b', template_name=None, template_loader=loader,
     
    158158            c[key] = value()
    159159        else:
    160160            c[key] = value
    161     return HttpResponse(t.render(c), mimetype=mimetype)
     161    return HttpResponse(t.iter_render(c), mimetype=mimetype)
    162162
    163163def archive_week(request, year, week, queryset, date_field,
    164164        template_name=None, template_loader=loader,
     
    206206            c[key] = value()
    207207        else:
    208208            c[key] = value
    209     return HttpResponse(t.render(c), mimetype=mimetype)
     209    return HttpResponse(t.iter_render(c), mimetype=mimetype)
    210210
    211211def archive_day(request, year, month, day, queryset, date_field,
    212212        month_format='%b', day_format='%d', template_name=None,
     
    270270            c[key] = value()
    271271        else:
    272272            c[key] = value
    273     return HttpResponse(t.render(c), mimetype=mimetype)
     273    return HttpResponse(t.iter_render(c), mimetype=mimetype)
    274274
    275275def archive_today(request, **kwargs):
    276276    """
     
    339339            c[key] = value()
    340340        else:
    341341            c[key] = value
    342     response = HttpResponse(t.render(c), mimetype=mimetype)
     342    response = HttpResponse(t.iter_render(c), mimetype=mimetype)
    343343    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
    344344    return response
  • django/views/generic/list_detail.py

    === modified file 'django/views/generic/list_detail.py'
     
    8484        model = queryset.model
    8585        template_name = "%s/%s_list.html" % (model._meta.app_label, model._meta.object_name.lower())
    8686    t = template_loader.get_template(template_name)
    87     return HttpResponse(t.render(c), mimetype=mimetype)
     87    return HttpResponse(t.iter_render(c), mimetype=mimetype)
    8888
    8989def object_detail(request, queryset, object_id=None, slug=None,
    9090        slug_field=None, template_name=None, template_name_field=None,
     
    126126            c[key] = value()
    127127        else:
    128128            c[key] = value
    129     response = HttpResponse(t.render(c), mimetype=mimetype)
     129    response = HttpResponse(t.iter_render(c), mimetype=mimetype)
    130130    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
    131131    return response
  • django/views/generic/simple.py

    === modified file 'django/views/generic/simple.py'
     
    1515            dictionary[key] = value
    1616    c = RequestContext(request, dictionary)
    1717    t = loader.get_template(template)
    18     return HttpResponse(t.render(c), mimetype=mimetype)
     18    return HttpResponse(t.iter_render(c), mimetype=mimetype)
    1919
    2020def redirect_to(request, url, **kwargs):
    2121    """
  • django/views/static.py

    === modified file 'django/views/static.py'
     
    9292        'directory' : path + '/',
    9393        'file_list' : files,
    9494    })
    95     return HttpResponse(t.render(c))
     95    return HttpResponse(t.iter_render(c))
    9696
    9797def was_modified_since(header=None, mtime=0, size=0):
    9898    """
Back to Top