1

我想创建一个引擎,稍后在处理模板实例时将使用该引擎。

我不想在设置中定义它,因为其中定义的逻辑不应分布​​在任何地方,而应仅在特定情况下分布。

这是我所做的:

from django.template.engine import Engine


class ModelEngine(Engine):
    def find_template(self, name, dirs=None, skip=None):
        # some another logic to get a template instance
        ...

engine = ModelEngine()

# Usage
template_code = "{% include \"some_template.html\" %}"
Template(template_code, engine=engine).render(Context())

这个解决方案正确吗?不是从BaseEngine继承而是从Engine继承有什么问题吗?如果是,请提供一些建议。

4

1 回答 1

1

不需要仅仅为了从其他地方加载模板而覆盖模板引擎。相反,您只需要一个自定义加载器。下面是一些可能满足您需求的加载器示例代码:

from django.template import Origin, TemplateDoesNotExist
from django.template.loaders.base import Loader

class DBLoader(Loader):
    def get_template_sources(self, template_name):
        yield Origin(
            name=template_name,
            template_name=template_name,
            loader=self,
        )
    
    def get_contents(self, origin):
        try:
            # Assuming name of your model and field that has template name
            instance = YourTemplateModel.objects.get(template_name=origin.template_name)
            return instance.content
        except (YourTemplateModel.MultipleObjectsReturned, YourTemplateModel.DoesNotExist):
            raise TemplateDoesNotExist(template_name)

接下来,您可以简单地将这个加载器添加到您的TEMPLATES设置中以使用它:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates']
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
            'loaders': [
                'django.template.loaders.filesystem.Loader',
                'django.template.loaders.app_directories.Loader',
                'path.to.DBLoader',
            ],
        },
    },
]

请注意,还有一个名为django-dbtemplates的包已经这样做了,它可能比这里的基本实现更有效。

于 2021-07-05T17:42:05.170 回答