Django:高效的模板/字符串分离和覆盖

12
我有一个通用的 Django 视图,用于渲染模板。该模板在一个应用程序中,其他项目将使用该应用程序。导入项目通常会对应用程序提供的视图进行子类化。该视图具有默认模板,其中使用通用措辞完成工作。
99% 的情况下,子类化视图只想更改文本,因此,我正在寻找一种允许类的用户以最有效的方式替换模板中的措辞的方法,而不是让他们为了更改非标记措辞而复制模板。
目前已探索的选项:
- 包含仅包含文本部分的模板片段,使用应用程序可以覆盖它们(魔术,需要大量用户工作)。 - 视图上的 template_strings 方法,该方法提供字符串字典,这些字符串最终出现在模板上下文中,子类可以覆盖它们。 - 利用(滥用?)翻译系统,使应用程序提供默认的英语翻译,并且使用代码可以提供自己的翻译(尚未实现,仅是一个想法)。 - 通过 AppConfig 实现上述“template_strings”,但这似乎很糟糕,可能会变得非常难以处理,因为有很多英文字符串。如果这样做,我会创建一个类似于上下文的设置,以便您不必重新声明所有字符串。
似乎应该通过子类化完成一项完整的工作并仅为文本提供替代字符串的解决方案。是否有比上述方法更好的方法?传统的做法?我是否遗漏了什么?
(django 1.11 Python 3.6.2)
2个回答

2

您可以选择继承TemplateView或将ContextMixin添加到您的视图中,然后像这样覆盖get_context_data函数:

from django.views.generic import TemplateView

class BaseView(TemplateView):
    template_name = "common.html"

class SubView(BaseView):
    def get_context_data(self, **kwargs):
        context = super(SubView, self).get_context_data(**kwargs)
        context['content'] = "Some sub view text"
        return context

更新:使用模板覆盖

如果您想将文本分离出来,这是更好的方法。 为了允许跨应用程序轻松且DRY地覆盖模板,您可能需要安装此软件包(其他一些详细信息在此处)。

我们与上面类似地定义它,但是改变了template_name

from django.views.generic import TemplateView

    class BaseView(TemplateView):
        template_name = "main.html"

    # on another app
    class SubView(BaseView):
        template_name = "sub_view.html"

那么,神奇的是您可以像这样 extends 并覆盖 BaseView 模板的 block

base_app/templates/main.html

<p>I'm Common Text</p>
{% block main %}
  <p>I'm Base View</p>
{% endblock %}

sub_app/templates/sub_view.html

{% extends "base_app:main.html" %}
{% block main %}
  <p>I'm Sub View</p>
{% endblock %}

结果将会是:
<p>I'm Common Text</p>
<p>I'm Sub View</p>

这是点号2的实现,几乎与我实现的相同。在get_context_data中有很多字符串很糟糕,并且将其转移到get_context中的某个位置似乎错过了重点。我想翻译模块可能是可行的方法,即多个英语翻译覆盖其中一个。 - Aiden Bell
1
@AidenBell:请不要使用英语翻译,我认为它很丑。我更新了我的答案,采用了通过覆盖模板的新方式。 - Nathan Do
我选择了这个作为答案,但说实话,所有的解决方案都不是很理想,也不是很令人满意。这似乎是Django的问题,而不是回答者的问题,我认为这代表了最符合语言习惯的解决方案,但不是我将要采取的方式。 - Aiden Bell
好的,我明白了,请更新一下如果你找到了更好的解决方案,以供其他人参考。 - Nathan Do
我一定会。 - Aiden Bell

0
据我所知,您已经很好地涵盖了选项。我的示例可能只是模板字符串的变体,但也许仍会有所帮助...
class DefaultStringProvider():
    TITLE = 'Hello'
    DESCRIPTION = 'Original description'
    CATEGORY = 'Stuff'

class MyTemplateBaseView(TemplateView):
    def get_context_data(self, **kwargs):
        return super(MyTemplateBaseView, self).get_context_data(
            provider=self.get_string_provider(), **kwargs)

    def get_string_provider(self):
        return DefaultStringProvider()

class OtherView(MyTemplateBaseView):
    template_name = 'welcome.html'

    def get_string_provider(self):
        p = DefaultStringProvider()
        p.TITLE = 'Hello'
        p.DESCRIPTION = 'New description'
        return p

这个想法是有一个默认的字符串提供者,并且基础视图通过get_string_provider()来填充上下文。

这将至少非常清晰地表明哪些字符串可以被用户扩展基类覆盖,而且不会干扰翻译。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接