Django: эффективное разделение шаблонов/строк и переопределение

У меня есть общий вид Django, который отображает шаблон. Шаблон находится в приложении, которое будут использовать другие проекты. Импорт проектов обычно подклассифицируется в представлении "Просмотр приложения". В представлении есть шаблон по умолчанию, который выполняет задание с общей формулировкой.

99% времени, подклассирование Views будет хотеть только изменять текст, поэтому вместо того, чтобы заставить их дублировать шаблон для изменения формулировки без разметки, я ищу способ разрешить пользователям класса чтобы заменить формулировку в шаблоне наиболее эффективным способом.

Параметры, изученные до сих пор:

  • частичные части шаблона, содержащие только текст, который может использовать приложения (магия, много работы пользователя)
  • A template_strings на представлении, которое предоставляет бит строк, которые заканчиваются в контексте шаблона, которые подклассы могут переопределять
  • Использование (злоупотребление?) системы перевода, так что приложение предоставляет английские переводы по умолчанию, а использование кода может обеспечить их собственные переводы вместо этого (на самом деле это не работало, а просто идея).
  • Выполнение вышеприведенного template_strings через AppConfig, но это кажется... yucky, как будто это может стать очень неуязвимым с множеством английских строк. Если я это сделаю, я создам контекстно-подобную настройку, поэтому вам не нужно повторно объявлять все строки

Похоже, что проблема должна быть решена для подкласса представления, которое выполняет полную работу и просто предоставляет альтернативные строки для текста. Есть ли лучший способ, чем выше? Конвенция? Что-то мне не хватает?

(django 1.11 Python 3.6.2)

Ответ 1

Вы можете либо наследовать 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

Обновление: использование переопределения шаблона

Если вы хотите отделить текст, это лучший способ пойти Чтобы разрешить простой и суровый шаблон замены в приложениях, вам может потребоваться установить этот пакет (некоторые другие детали здесь)

Определим его так же, как указано выше, но вместо этого изменим 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 и переопределить block шаблона BaseView следующим образом:

base_app/шаблоны/main.html

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

sub_app/шаблоны/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

Афайк, вы хорошо изучили варианты. Мой пример, вероятно, всего лишь вариант строк шаблона, но, возможно, он все равно помогает...

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().

По крайней мере будет ясно, какие строки можно переопределить для пользователя, расширяющего базовый класс, и он не будет мешать переводам.