Login

A templatetag to insert the output of another view (or local URL)

Author:
jamesgpearce
Posted:
June 17, 2009
Language:
Python
Version:
1.0
Score:
5 (after 5 ratings)

Inserts the output of a view, using fully qualified view name (and then some args), a or local Django URL.

{% view view_or_url arg[ arg2] k=v [k2=v2...] %}

This might be helpful if you are trying to do 'on-server' AJAX of page panels. Most browsers can call back to the server to get panels of content asynchonously, whilst others (such as mobiles that don't support AJAX very well) can have a template that embeds the output of the URL synchronously into the main page. Yay! Go the mobile web!

Follow standard templatetag instructions for installing.

IMPORTANT: the calling template must receive a context variable called 'request' containing the original HttpRequest. This means you should be OK with permissions and other session state.

ALSO NOTE: that middleware is not invoked on this 'inner' view.

Example usage...

Using a view name (or something that evaluates to a view name):

{% view "mymodule.views.inner" "value" %}
{% view "mymodule.views.inner" keyword="value" %}
{% view "mymodule.views.inner" arg_expr %}
{% view "mymodule.views.inner" keyword=arg_expr %}
{% view view_expr "value" %}
{% view view_expr keyword="value" %}
{% view view_expr arg_expr %}
{% view view_expr keyword=arg_expr %}

Using a URL (or something that evaluates to a URL):

{% view "/inner" %}
{% view url_expr %}

(Note that every argument will be evaluated against context except for the names of any keyword arguments. If you're warped enough to need evaluated keyword names, then you're probably smart enough to add this yourself!)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
from django.template import Library, Node, TemplateSyntaxError, Variable
from django.conf import settings
from django.core import urlresolvers

register = Library()

class ViewNode(Node):
    def __init__(self, url_or_view, args, kwargs):
        self.url_or_view = url_or_view
        self.args = args
        self.kwargs = kwargs

    def render(self, context):
        if 'request' not in context:
            return ""
        request = context['request']

        url_or_view = Variable(self.url_or_view).resolve(context)
        try:
            urlconf = getattr(request, "urlconf", settings.ROOT_URLCONF)
            resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
            view, args, kwargs = resolver.resolve(url_or_view)
        except:
            view = urlresolvers.get_callable(url_or_view, True)
            args = [Variable(arg).resolve(context) for arg in self.args]
            kwargs = {}
            for key, value in self.kwargs.items():
                kwargs[key] = Variable(value).resolve(context)

        try:
            if callable(view):
                return view(context['request'], *args, **kwargs).content
            raise "%r is not callable" % view
        except:
            if settings.TEMPLATE_DEBUG:
                raise
        return ""


def do_view(parser, token):
    """
    Inserts the output of a view, using fully qualified view name (and then some
    args), a or local Django URL.

     {% view view_or_url arg[ arg2] k=v [k2=v2...] %}

    This might be helpful if you are trying to do 'on-server' AJAX of page
    panels. Most browsers can call back to the server to get panels of content
    asynchonously, whilst others (such as mobiles that don't support AJAX very
    well) can have a template that embeds the output of the URL synchronously
    into the main page. Yay! Go the mobile web!

    Follow standard templatetag instructions for installing.

    IMPORTANT: the calling template must receive a context variable called
    'request' containing the original HttpRequest. This means you should be OK
    with permissions and other session state.

    ALSO NOTE: that middleware is not invoked on this 'inner' view.

    Example usage...

    Using a view name (or something that evaluates to a view name):
     {% view "mymodule.views.inner" "value" %}
     {% view "mymodule.views.inner" keyword="value" %}
     {% view "mymodule.views.inner" arg_expr %}
     {% view "mymodule.views.inner" keyword=arg_expr %}
     {% view view_expr "value" %}
     {% view view_expr keyword="value" %}
     {% view view_expr arg_expr %}
     {% view view_expr keyword=arg_expr %}

    Using a URL (or something that evaluates to a URL):
     {% view "/inner" %}
     {% view url_expr %}


    (Note that every argument will be evaluated against context except for the
    names of any keyword arguments. If you're warped enough to need evaluated
    keyword names, then you're probably smart enough to add this yourself!)

    """

    args = []
    kwargs = {}
    tokens = token.split_contents()
    if len(tokens)<2:
        raise TemplateSyntaxError, ("%r tag requires one or more arguments" %
                                    token.contents.split()[0])
    tag_name = tokens.pop(0)
    url_or_view = tokens.pop(0)
    for token in tokens:
        equals = token.find("=")
        if equals == -1:
            args.append(token)
        else:
            kwargs[str(token[:equals])] = token[equals+1:]
    return ViewNode(url_or_view, args, kwargs)

register.tag('view', do_view)

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

jamesgpearce (on June 17, 2009):

Oh - and I should add that you need to watch out for recursion of course. Don't try to embed the current view, or one which creates a loop back to it.

I guess that goes without saying but... well I said it anyway.

#

Ciantic (on February 2, 2011):

This is a great idea, it allows to do ajax ready parts of site. (Joomla world "module" or "blocks" in Drupal world)

All different parts of site should be just a view that is called using view-tag.

#

stormlifter (on September 15, 2011):

So if I get this right this basically makes it so you can use views to replace templatetags and filters?

#

stormlifter (on September 15, 2011):

Line #33 seems odd. Don't exceptions have to be a class or an instance?

#

Please login first before commenting.