django-allauth динамически меняет шаблоны (поддержка BIDI)

Вопрос:

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

/templates
/accounts/
/includes/
/rtl
/accounts/
/includes/
...
...

django-allauth попытается загрузить шаблоны из /templates/accounts независимо от того, что (жестко запрограммировано в их представлениях), но я хочу загрузить версию RTL (справа налево) на основе контекстной переменной, когда это необходимо, поэтому я подумал о четырех решениях, но ни один из них не кажется мне достаточно хорошим (я не говорю, что я их не буду делать, я говорю, что я не могу найти лучший способ, если он есть)

  1. Задайте условие в моих переопределениях для загрузки версий LTR или RTL (для которых требуется условное значение в /templates/accounts, версия LTR с шаблоном где-то еще и версия RTL в /templates/rtl/accounts.

  2. Создайте тег шаблона, который имеет параметр с именем шаблона и динамически загружает шаблон, это выглядит как пустая трата ресурсов

  3. Создайте беспорядок в основных шаблонах с тоннами логики, чтобы он переключался между LTR и RTL, когда это было необходимо (для этого потребуется тонна логики в шаблоне, что не очень хорошо)

  4. Вилка allauth в мой проект и добавить логику к представлениям. Я действительно не хочу этого делать, потому что в будущем это будет поддерживать ад.

Я не использую стандартный django i18n, поэтому я не могу использовать настройки BIDI.

У кого-то есть лучший подход к этому?

Лучший ответ:

Решив это, я в конце концов должен был использовать пользовательский загрузчик шаблонов для изменения каталога шаблонов на лету в момент запроса. Я последовал за очень полезным учебным пособием от ребята в разное время: http://opensource.washingtontimes.com/blog/2010/feb/17/loading-templates-based-request-headers-django/

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

Мой код:

<projectname>/settings/defaults.py

Мы загружаем загрузчик шаблонов FIRST, поэтому мы можем обрабатывать данные, прежде чем django загрузит что-нибудь. Если в нашем коде что-то не получится, оно вернется к загрузчикам django по умолчанию.

TEMPLATE_LOADERS = (
    'projectname.templateloaders.arabic.load_template_source',
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
    #'django.template.loaders.eggs.Loader',
)

<имя_проекта>/middleware/templaterequest.py

# -*- coding: utf-8 -*-

try:
    from threading import local
except ImportError:
    from django.utils._threading_local import local

from apps.locales.models import Locale
from apps.markets.models import Market

# for more info:
# http://opensource.washingtontimes.com/blog/2010/feb/17/loading-templates-based-request-headers-django/

_thread_locals = local()


def get_current_request():
    return getattr(_thread_locals, 'arabic', None)


class RequestMiddleware(object):

    """
    This middleware will store the market.rtl value at each request that is made.
    Basically here you can do anything that you can get from the request.

    In this case we get the locale and the market settings and extract the RTL
    value, which we store in a local thread in memory an will be retrieved
    later by the template loader when calling for get_current_request()
    """
    def process_request(self, request):
        site = request.META['HTTP_HOST']
        locale = Locale.objects.get(site=site)
        market = Market.objects.get(locale=locale)

        _thread_locals.arabic = market.rtl

<имя_проекта>/templateloaders/arabic.py

# -*- coding: utf-8 -*-

from django.conf import settings
from django.template.loader import BaseLoader, TemplateDoesNotExist
from django.utils._os import safe_join

from tipx.middleware.templaterequest import get_current_request

def get_template_sources(template_name, template_dirs=None):

    """
    This class will modify the template directory in case the market has
    RTL activated in the market settings. If RTL if False it will pass and
    let the standard django template loaders to work.

    Explanation of how it behaves (it weird...) the request comes trough and
    hits first our code, tries to determine if the market is arabic or not.
    It it arabic it changes the template directory to /rtl/, but for example
    third party templates are not there (except for the overrides), so it will
    continue processing through the template loaders until it finds the right
    template. This guarantees that no matter how twisted our template locations
    are, it will always load the right templates in the right moment even
    when the templates have includes from RTL to english.
    """
    arabic = get_current_request()
    if arabic:
        # Loop through the template dirs
        for directory in settings.TEMPLATE_DIRS:
            new_directory = directory + '/rtl/'
            yield safe_join(new_directory, template_name)


def load_template_source(template_name, template_dirs=None):
    for filepath in get_template_sources(template_name, template_dirs):
        try:
            file = open(filepath)
            try:
                return (file.read().decode(settings.FILE_CHARSET), filepath)
            finally:
                file.close()
        except IOError:
            pass
    raise TemplateDoesNotExist(template_name)
load_template_source.is_usable = True

Последнее, что нужно иметь нашу папку шаблонов RTL. Если какой-либо из ваших шаблонов включает, вам нужно будет добавить имя папки, которое у вас есть для вашей арабской версии, например:

Оригинал включает:

{% include 'whatever/template.html' %}

RTL включает:

{% include 'rtl/whatever/template' %}

Если кто-то найдет этот ответ неполным, просто скажите мне! 🙂

Оцените статью
TechArks.Ru
Добавить комментарий