模板包含标签:如果不存在,请选择另一个模板

时间:2015-06-14 10:10:26

标签: python django templates

我想根据请求添加不同的模板。例如:

假设该请求具有:

request.country = 'Spain'
request.city = 'Madrid'

我想要包含“index.html”视图,但是:

----如果myapp / index_madrid.html存在

{% include "myapp/index_madrid.html" %}

---- elif myapp / index_spain.html存在

   {% include "myapp/index_spain.html" %}

----否则转到默认版本

   {% include "myapp/index.html" %}

如何以透明的方式实现此行为?我的意思是,我想做类似的事情:

{% my_tag_include "myapp/index.html" %}
{% my_tag_include "myapp/another_view.html" with p='xxx' only%}
{% my_tag_include "myapp/any_view.html" with p='sss' a='juan' %}

并实现我之前解释过的级联加载。

由于

4 个答案:

答案 0 :(得分:2)

您可以实现自定义模板标记来检查模板是否存在:

from django import template

register = template.Library()


def template_exists(template_name):
    try:
        django.template.loader.get_template(template_name)
        return True
    except template.TemplateDoesNotExist:
        return False
register.filter('template_exists', template_exists) 

在你的模板中:

 {% if template_exists  "myapp/index_"add:request.city|add:".html" %}
     {% include "myapp/index_"add:request.city|add:".html" %}
 {% elif template_exists  "myapp/index_"add:request.country|add:".html" %}
     {% include "myapp/index_"add:request.country|add:".html" %}
 {% else %}
      {% include "myapp/index.html" %}

修改: 您可以通过模板标记完成所有逻辑:

from django import template

register = template.Library()

@register.simple_tag(takes_context=True)
def existing_template(context):
    request = context["request"]
    if django.template.loader.get_template("myapp/index_"+ request.city+".html"):
        return "myapp/index_"+ request.city+".html"
    elif  django.template.loader.get_template("myapp/index_"+ request.country+".html"):
        return "myapp/index_"+ request.country+".html"
    else:
        return "myapp/index.html"

在你的模板中:

{% include required_template %}

答案 1 :(得分:2)

一种可能性是在视图中实现这种逻辑:

# views.py
from django.template.loader import select_template

class MyView(View):
    def get(self, request):
        include_template = select_template([
            'myapp/index_{}.html'.format(request.city),
            'myapp/index_{}.html'.format(request.country),
            'myapp/index.html'
        ])

        ctx = {
            'include_template': include_template
        }

        return render(request, 'myapp/base.html', ctx)

# myapp/base.html
{% include include_template %}

select_template() 将返回已存在的传递列表中的第一个模板。 include标记支持包含从Django 1.7开始的已编译模板,因此如果您使用的是1.7或更高版本,这应该可以正常工作。

更新:重复使用多个视图

# utils.py
from django.template.loader import select_template

def get_approriate_template(tokens, app_name):
    templates = ['{}/index_{}.html'.format(app_name, x) for x in tokens]
    templates.append('{}/index.html'.format(app_name))
    return select_template(templates)

# views.py
from .utils import get_approriate_template

class MyView(View):
    def get(self, request):
        tokens = [request.city, request.country]
        ctx = {
            'include_template': get_appropriate_template(tokens, app_name='myapp')
        }

        return render(request, 'myapp/base.html', ctx)

更新:从模板标记中呈现模板

# templatetags/myapp_extras.py
from django import template

register = template.Library()

@register.simple_tag(takes_context=True)
def my_tag_include(context):
    from django.template.loader import select_template
    include_template = select_template([
        'myapp/index_{}.html'.format(context['request'].city),
        'myapp/index_{}.html'.format(context['request'].country),
        'myapp/index.html'
    ])
    return include_template.render(context)

# myapp/base.html
{% load myapp_extras %}
{% my_tag_include %}        

答案 2 :(得分:1)

您可以通过编写自己的模板标记来执行此操作,该标记返回存在的有效模板。

方法-1使用Script Error.

<强> some_app / templatetags / some_app_extras.py

var window = {google: {}};
var google = {maps: {}};
(function() {

  function getScript(src) {
      importScripts(src);
    //document.write('<' + 'script src="' + src + '"><' + '/script>');
  }

  var modules = google.maps.modules = {};
  google.maps.__gjsload__ = function(name, text) {
    modules[name] = text;
  };

  google.maps.Load = function(apiLoad) {
    delete google.maps.Load;
    apiLoad([0.009999999776482582,[[["http://mt0.googleapis.com/vt?lyrs=m@306000000\u0026src=api\u0026hl=de-DE\u0026","http://mt1.googleapis.com/vt?lyrs=m@306000000\u0026src=api\u0026hl=de-DE\u0026"],null,null,null,null,"m@306000000",["https://mts0.google.com/vt?lyrs=m@306000000\u0026src=api\u0026hl=de-DE\u0026","https://mts1.google.com/vt?lyrs=m@306000000\u0026src=api\u0026hl=de-DE\u0026"]],[["http://khm0.googleapis.com/kh?v=174\u0026hl=de-DE\u0026","http://khm1.googleapis.com/kh?v=174\u0026hl=de-DE\u0026"],null,null,null,1,"174",["https://khms0.google.com/kh?v=174\u0026hl=de-DE\u0026","https://khms1.google.com/kh?v=174\u0026hl=de-DE\u0026"]],[["http://mt0.googleapis.com/vt?lyrs=h@306000000\u0026src=api\u0026hl=de-DE\u0026","http://mt1.googleapis.com/vt?lyrs=h@306000000\u0026src=api\u0026hl=de-DE\u0026"],null,null,null,null,"h@306000000",["https://mts0.google.com/vt?lyrs=h@306000000\u0026src=api\u0026hl=de-DE\u0026","https://mts1.google.com/vt?lyrs=h@306000000\u0026src=api\u0026hl=de-DE\u0026"]],[["http://mt0.googleapis.com/vt?lyrs=t@132,r@306000000\u0026src=api\u0026hl=de-DE\u0026","http://mt1.googleapis.com/vt?lyrs=t@132,r@306000000\u0026src=api\u0026hl=de-DE\u0026"],null,null,null,null,"t@132,r@306000000",["https://mts0.google.com/vt?lyrs=t@132,r@306000000\u0026src=api\u0026hl=de-DE\u0026","https://mts1.google.com/vt?lyrs=t@132,r@306000000\u0026src=api\u0026hl=de-DE\u0026"]],null,null,[["http://cbk0.googleapis.com/cbk?","http://cbk1.googleapis.com/cbk?"]],[["http://khm0.googleapis.com/kh?v=86\u0026hl=de-DE\u0026","http://khm1.googleapis.com/kh?v=86\u0026hl=de-DE\u0026"],null,null,null,null,"86",["https://khms0.google.com/kh?v=86\u0026hl=de-DE\u0026","https://khms1.google.com/kh?v=86\u0026hl=de-DE\u0026"]],[["http://mt0.googleapis.com/mapslt?hl=de-DE\u0026","http://mt1.googleapis.com/mapslt?hl=de-DE\u0026"]],[["http://mt0.googleapis.com/mapslt/ft?hl=de-DE\u0026","http://mt1.googleapis.com/mapslt/ft?hl=de-DE\u0026"]],[["http://mt0.googleapis.com/vt?hl=de-DE\u0026","http://mt1.googleapis.com/vt?hl=de-DE\u0026"]],[["http://mt0.googleapis.com/mapslt/loom?hl=de-DE\u0026","http://mt1.googleapis.com/mapslt/loom?hl=de-DE\u0026"]],[["https://mts0.googleapis.com/mapslt?hl=de-DE\u0026","https://mts1.googleapis.com/mapslt?hl=de-DE\u0026"]],[["https://mts0.googleapis.com/mapslt/ft?hl=de-DE\u0026","https://mts1.googleapis.com/mapslt/ft?hl=de-DE\u0026"]],[["https://mts0.googleapis.com/mapslt/loom?hl=de-DE\u0026","https://mts1.googleapis.com/mapslt/loom?hl=de-DE\u0026"]]],["de-DE","US",null,0,null,null,"http://maps.gstatic.com/mapfiles/","http://csi.gstatic.com","https://maps.googleapis.com","http://maps.googleapis.com",null,"https://maps.google.com","https://gg.google.com","http://maps.gstatic.com/maps-api-v3/api/images/","https://www.google.com/maps",0],["http://maps.gstatic.com/maps-api-v3/api/js/21/3/intl/de_ALL","3.21.3"],[141790386],1,null,null,null,null,null,"",["geometry"],null,0,"http://khm.googleapis.com/mz?v=174\u0026","AIzaSyDQi59vEjsIzBM-AFMeDbszVsOckQOb5A8","https://earthbuilder.googleapis.com","https://earthbuilder.googleapis.com",null,"http://mt.googleapis.com/vt/icon",[["http://mt0.googleapis.com/vt","http://mt1.googleapis.com/vt"],["https://mts0.googleapis.com/vt","https://mts1.googleapis.com/vt"],null,null,null,null,null,null,null,null,null,null,["https://mts0.google.com/vt","https://mts1.google.com/vt"],"/maps/vt",306000000,132],2,500,[null,"http://g0.gstatic.com/landmark/tour","http://g0.gstatic.com/landmark/config",null,"http://www.google.com/maps/preview/log204","","http://static.panoramio.com.storage.googleapis.com/photos/",["http://geo0.ggpht.com/cbk","http://geo1.ggpht.com/cbk","http://geo2.ggpht.com/cbk","http://geo3.ggpht.com/cbk"]],["https://www.google.com/maps/api/js/master?pb=!1m2!1u21!2s3!2sde-DE!3sUS!4s21/3/intl/de_ALL","https://www.google.com/maps/api/js/widget?pb=!1m2!1u21!2s3!2sde-DE"],null,0,0,"/maps/api/js/ApplicationService.GetEntityDetails",0], loadScriptTime);
  };

    importScripts(
    'http://maps.gstatic.com/maps-api-v3/api/js/21/3/intl/de_ALL/main.js'
    , 'http://maps.gstatic.com/maps-api-v3/api/js/21/3/intl/de_ALL/geometry.js'
    );

})();

在您的模板中:

assignment_tag

我们使用赋值标记,并在注册标记时通过传递from django import template from django.template.loader import select_template register = template.Library() @register.assignment_tag(takes_context=True) def get_valid_template(context): city_template = 'myapp/index_{}.html'.format(context['request'].city) country_template = 'myapp/index_{}.html'.format(context['request'].country) index_template = 'myapp/index.html' templates_list = [city_template, country_template, index_template] valid_template = select_template(templates_list) return valid_template.name 参数将上下文传递给它。由于我们有上下文,因此我们可以访问{% load some_app_extras %} {% get_valid_template as valid_template %} {% include valid_template %} 以获取takes_context=Truerequest。在此之后,我们使用django的city函数并传递一个模板列表,这些模板将返回列表中找到的第一个模板。

然后在我们的模板中,我们可以使用此模板标记获取country并使用此变量来呈现select_template()

方法-2使用valid template

如果您只想按照评论中提到的那样在1行中进行渲染,那么您可以使用valid template。您不需要在变量中分配模板名称,然后由simple_tag内置模板标记稍后完成渲染。 simple_tag将自动显示必要的模板,因为它已经在模板标记代码中呈现。

<强> some_app / templatetags / some_app_extras.py

include

在您的模板中:

get_template_tag

答案 3 :(得分:0)

最后,我通过创建自定义简单标记解决了问题,例如:

@register.simple_tag(takes_context=True)
def my_own_include(context, *args):
    #I get the request and create a list of possible template views
    return select_template(list_of_posible_views).render(context)

在.html文件中,我将此标记称为:

{% my_own_include 'index.html' %}

感谢各位的帮助。