Django使用不同的基temp呈现任何url

2024-04-24 09:37:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我想能够在我的项目中使用不同的基础模板呈现一些或所有的视图。换句话说,对于url /some/view,我希望能够使用/inline/some/view并使其呈现相同的内容,但使用不同的基模板。在

修改每个视图以接受不同的模板不是一个选项,因为我希望在项目中的所有应用程序中应用此行为,包括django.contrib.auth。在

到目前为止,我已经网址.py公司名称:

url("^inline/(?P<uri>.*)", format.inline, name='inline'),

还有风景,格式.py公司名称:

^{pr2}$

我不知道从这里到哪里去。我可以在调用view()之前修改整个模板链,以便template_response.render()做正确的事情吗?在

也许我完全不了解这种方法,应该考虑一种中间件解决方案,但我很赞同这种行为键入url的想法,因为以后很容易向内容人员解释。在

更新

我能够达到我想要的效果,但执行力严重不足。我是这样做的:

  • 复制了我希望内嵌到^{中的视图的模板
  • {% extends base.html %}替换为{% extends inline/base.html %}
  • 因此修改了视图:

    from django.core.urlresolvers import resolve
    
    def inline(request, uri=''):
    
        # get the view that would normally handle this request
        view, args, kwargs = resolve('/' + uri)
    
        # call the view
        kwargs['request'] = request
        template_response = view(*args, **kwargs)
        response.template_name = os.path.join('inline', response.template_name)
        return response
    

我不喜欢这个解决方案,因为它需要管理那些内联模板,当项目中的应用程序发生变化时,这些模板会被替换/更新,等等。我仍然非常希望有一个更干净的解决方案。在

更新2:解决方案

chriswesseling是100%正确的;一个定制的模板加载程序正是我所需要的。对于后代来说,这是我的实现。在

应用程序/加载程序.py公司名称:

from django.conf import settings
from django.template.loader import BaseLoader
from django.template.base import TemplateDoesNotExist
import os


class BaseTemplateOverrideLoader(BaseLoader):
    """
    Load templates from a specified subdirectory in the current app's directory.
    """
    subdir = 'templates'

    def load_template_source(self, template_name, template_dirs=None):

        template_dir = os.path.join(
            os.path.dirname(os.path.realpath(__file__)),
            self.subdir
        )

        try:
            t = os.path.join(template_dir, template_name)
            with open(t, 'rb') as fp:
                return (fp.read().decode(settings.FILE_CHARSET), template_dir)
        except IOError:
            pass
        raise TemplateDoesNotExist(template_name)


class InlineTemplateLoader(BaseTemplateOverrideLoader):
    """
    Override the location of base.html for inline views.
    """
    is_usable = True
    subdir = 'templates/inline'

# ... other custom override classes here ....

应用程序/视图/内联.py公司名称:

from django.conf import settings
from django.core.urlresolvers import resolve
from django.template import loader


def default(request, slug=None):

    view, args, kwargs = resolve('/' + slug)

    old_loaders = settings.TEMPLATE_LOADERS

    # Temporarily insert the inline template loader into TEMPLATE_LOADERS;
    # we must also force BaseLoader to reload all templates loaders since
    # they are cached at compile time.
    settings.TEMPLATE_LOADERS = ('app.loaders.InlineTemplateLoader', ) + \
        settings.TEMPLATE_LOADERS
    loader.template_source_loaders = None

    # now call the original view that handles this request
    kwargs['request'] = request
    response = view(*args, **kwargs)
    response_string = response.render()

    # restore the template loaders to their original condition
    settings.TEMPLATE_LOADERS = old_loaders
    loader.template_source_loaders = None

    return response_string

应用程序/模板/内联/基本.html公司名称:

{% comment %}
inline/base.html
    -- render just the main content without any styles etc,
       for loading as inline content via ajax or whatever.
{% endcomment %}
{% block main %}{% endblock %}

Tags: thedjangonamefromimportview模板settings