当前位置: 首页 > 知识库问答 >
问题:

django allauth动态更改模板(BIDI支持)

杨宏儒
2023-03-14

我正在尝试为我正在工作的网站添加对阿拉伯语的支持,所以目前我的模板是这样的

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

无论如何,django-allauth 都会尝试从 /templates/accounts 加载模板(在他们的视图中是硬编码的),但我想在必要时基于上下文变量加载 RTL(从右到左)版本,所以我考虑了四个解决方案,但它们对我来说似乎都不够好(我不是说我不会这样做, 我是说我找不到更好的方法,如果有的话)

> < li>

在“我的覆盖”中设置一个条件以加载LTR或RTL版本(这将需要< code>/templates/accounts中的条件,在其他地方带有模板的LTR版本和< code >/templates/RTL/accounts 中的RTL版本)。

创建一个带有模板名参数的模板标签,并动态加载模板,这看起来像是浪费资源

用大量的逻辑在主模板中创建一个混乱的环境,这样它就可以在需要时在LTR和RTL之间切换(这将需要大量的逻辑在模板中,这并不好)

将allauth分支到我的项目中,并将逻辑添加到视图中。我真的不想这么做,因为这样会让以后的维护变成地狱。

我没有使用标准的 django i18n,所以我无法使用双向设置。

有人对此有更好的方法吗?

共有1个答案

宰父衡
2023-03-14

解决了它,最后我不得不使用自定义模板加载器在请求的那一刻即时更改模板 directoy。我遵循了华盛顿时报的人的一个非常有用的教程:http://opensource.washingtontimes.com/blog/2010/feb/17/loading-templates-based-request-headers-django/

我不觉得创建一个本地线程来存储请求(在我的例子中是上下文值)的想法很花哨,但这似乎是将数据实际传递给模板加载器的唯一方法。

我的代码:

我们首先加载模板加载器,这样我们就可以在 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',
)
# -*- 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
# -*- 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's weird...) the request comes trough and
    hits first our code, tries to determine if the market is arabic or not.
    It it's 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' %}

劳教包括:

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

如果有人发现这个答案不完整,请告诉我!:)

 类似资料:
  • 提示: ●一个地图,最多支持4种模板。 ●新增字段设置字段名称及字段类型。 操作步骤: 1)在动态模板中点击新增字段弹出新增字段窗口。 2)填写字段名称及选择字段类型,点击确定后,在内容字段下显示新增字段。 注意: ①字段名称不能出现重复。 ②字段名称及字段类型可以进行编辑和删除。 ③鼠标左键选择字段可以进行字段顺序调整。 提示: ●勾选 "提交发布动态时所在位置" ,在手机端发布动态的时候,会定

  • 我的模板中当前有以下代码: 其中是测试套件的名称,是该测试套件中失败测试用例的列表。我想知道如何才能改变到类似于其中在循环的每次迭代中递增。 UPDATE 在尝试@Gocht的答案后,我有以下代码: 在我的模板标签/get_percentage.py文件中 在我的模板中 我遇到了“字符串索引超出范围”错误。我试图寻找可能的原因,但没有一个答案与自定义模板标记相关。

  • 问题内容: 我正在从数据库中成功获取数据值。我也将它们存储到一个数组中。我需要将String数组作为项的加载,以响应执行的关键操作。每当获取按键值时,如何获取按键值,就如何重新加载项目。相反,我需要动态刷新项目。 问题答案:

  • 问题内容: 我正在以编程方式/动态方式创建原型bean。我希望启动后的这些bean在jmx控制台中。我如何区分它们?我正在使用注释以便将我的bean添加到jmx中, 我需要动态注入objectName。知道我该怎么办吗? 这是我的jmx配置: 问题答案: 您可以使用JMX命名策略来执行此操作。在工作中,我们使用一个接口: 我已经发布了实现RuntimeMetadataNamingStrategy命

  • 问题内容: 我正在尝试根据范围值使用不同的模板进行指令。 这是我到目前为止所做的,我不知道为什么它不起作用http://jsbin.com/mibeyotu/1/edit HTML元素: 指示: 问题答案: 1)您正在将内容作为属性传递到html中。试试这个: 代替: 2)指令的数据部分正在被编译,因此您应该使用其他东西。代替数据类型,例如datan-type。 链接在这里: http://jsb

  • 问题内容: 关于扩展django管理模板的一个(不是这样)快速问题。 我试图通过在结果行(row1和row2类)之间添加一个包含一些与该对象相关的对象的中间行来更改特定模型的结果列表(在django lingo中更改列表)。 我搜索了代码,但没有找到一种方法来执行此操作。非常感谢任何指针。代码也将有所帮助。 PS:我知道我应该设计自己的界面,但这是一个内部项目,我没有太多时间可以花时间。另外,dj