Django: How to include a view from within a template

瘦欲@ 提交于 2019-12-06 13:29:18

What you are going to need to use is a Django Custom Template Tag. You could simply pass a variable to it in your template, then have it decide which view and template to insert in your current template.

An Example:

Your Custom Template Tag (rend_item.py)

def return_template(item):
    template = 'null'

    context = {
            #Dictionary of things to pass back

    }
    #if statements that choose what 'template' should be
    if item == 5:
        template = 'item5.html'
    else:
        template = 'default.html'

    #render the template
    return render_to_string(template, context)

Template

 {# Make sure you load the py file where your template tag is located at the top #}
 {% load rend_item %}

      {% for item in cart %}

         {{ item|return_template }}         

      {% endfor %}

Even though the question was asked quite a while back, I was searching for the same kinda feature.

I believe I found the answer to the initial question and the follow up question to JcKelly's post -> 'filter as an actual view' (in which I assume filter means render).

I found this snippet (of a custom templatetag, see post JcKelley for info on custom templatetag) on the web:

https://djangosnippets.org/snippets/1568/

It was outdated for me. Thus I followed it's approach and came up with:

Your TemplateTag.py file

from django.template import Library, Node, Variable, TemplateSyntaxError
from django.conf import settings
from django.urls import reverse, resolve, NoReverseMatch
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:
            raise TemplateSyntaxError("No request has been made.")

        url_or_view = Variable(self.url_or_view).resolve(context)
        try:
            view, args, kwargs = resolve(reverse(url_or_view))
        except NoReverseMatch:
            view, args, kwargs = resolve(url_or_view)

        try:
            if callable(view):
                self.args += args
                self.kwargs.update(**kwargs)
                return (view(context['request'], *self.args, **self.kwargs)
                        .rendered_content)
            raise "%r is not callable" % view
        except:
            if settings.DEBUG:
                raise
        return None


@register.tag(name='view')
def do_view(parser, token):
    args, kwargs, tokens = [], {}, token.split_contents()
    if len(tokens) < 2:
        raise TemplateSyntaxError(
            f"{token.contents.split()[0]} tag requires one or more arguments")

    for t in tokens[2:]:
        kw = t.find("=")
        args.append(t) if kw == -1 else kwargs.update({str(t[:kw]): t[kw+1:]})
    return ViewNode(tokens[1], args, kwargs)

Your Template-file.html -> example of usage

Using a view's path name, (see https://docs.djangoproject.com/en/2.2/topics/http/urls/#naming-url-patterns for info on path names):

     {% view "mymodule:inner" %}
     {% view "mymodule:inner" "value" %}
     {% view "mymodule:inner" keyword="value" %}
     {% view "mymodule:inner" arg_expr %}
     {% view "mymodule:inner" keyword=arg_expr %}

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

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

Hope it may help someone!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!