如何在Django-allauth中覆盖模板?

18

根据其他问题的答案,这似乎非常简单:

但是,我完全无法让它工作。

示例应用程序设置中,我可以看到django-allauth应该希望其模板位于accountopenidsocialaccount目录中。 但是,当我将模板放在TEMPLATE_DIR/account/signup.html时,它不会被加载,signup视图显示与django-allauth捆绑的模板。 我错过了什么?

9个回答

25

我最终选择在 django-allauth 之前加载我的应用程序。在 settings.py 中:

INSTALLED_APPS = (
    ...
    'myapp',
    'allauth',
    'allauth.account'
)

这个解决方案与示例应用程序中的内容不同,但我无法以其他方式解决它。

它能够工作,但正如你所说的那样,这似乎不是最好的方法。我认为allauth应该在设置中有一个配置变量来指定所有模板的路径。 - miguelfg
谢谢你的回复 - 正如@miguelfg所说,它可以工作 - 但这似乎并不正确。你们有没有想过更好的方法? - awidgery
@awidgery 在 allauth 0.18 中,无论应用程序加载的先后顺序如何,模板覆盖都适用于我。我只需将我的模板放在正确的目录中,它们就会在默认模板之前被加载。 - Red
这仍然是我在Django 1.11.5和django-allauth 0.33.0中使用的唯一有效解决方案。@Red说得对 - 文档中没有提到。 - trubliphone

7

在模板目录中添加allauth的模板目录,就可以解决问题。在Django 1.8中,可以通过编辑模板目录设置TEMPLATES来完成此操作。

TEMPLATES = [
    ...
    'DIRS': [
        os.path.join(BASE_DIR, 'templates'),
        os.path.join(BASE_DIR, 'templates', 'allauth'),
    ],
]

我认为以下代码在其他版本的Django上也能正常运行。
TEMPLATE_DIRS = [
    os.path.join(BASE_DIR, 'templates'),
    os.path.join(BASE_DIR, 'templates', 'allauth'),
]

一个小修正。我试过了相同的事情,但自定义allauth模板没有被命中。原因是我的模板在rootDir/templates/allauth/templates文件夹下。所以需要两个更改。 (1)- 将 APP_DIRS : True 添加到模板 TEMPLATE_DIRS,(2)--将 account/ 复制到 allauth 文件夹下或使用 os.path.join(BASE_DIR,'templates','allauth','templates') - pravin

7
至今为止,我们现在使用的是Django-1.10.5版本,但django-allauth文档在这方面仍然不够详细。看起来似乎是Django查找第一个列出的应用程序的模板目录,而不管settings.pyTEMPLATES中的DIRS设置如何。我提供答案只是为了帮助您实现Adam Starrh的答案,并帮助解决反向URL的问题(在我处理这些问题之前,我遇到了错误)。
在您的urls.py文件中添加以下内容:
from allauth.account.views import SignupView, LoginView, PasswordResetView

class MySignupView(SignupView):
    template_name = 'signup.html'

class MyLoginView(LoginView):
    template_name = 'login.html'

class MyPasswordResetView(PasswordResetView):
    template_name = 'password_reset.html'

urlpatterns = [
    url(r'^accounts/login', MyLoginView.as_view(), name='account_login'),
    url(r'^accounts/signup', MySignupView.as_view(), name='account_signup'),
    url(r'^accounts/password_reset', MyPasswordResetView.as_view(), name='account_reset_password'),
]

目前views.py文件位于此处,所以你可以将上面的内容扩展到其他模板中。

我必须补充说明,在TEMPLATES中仍需要添加类似以下的内容:

'DIRS': [
    os.path.join(PROJECT_ROOT, 'templates', 'bootstrap', 'allauth', 'account'),
],

在这个例子中,如果你的模板位于 /templates/bootstrap/allauth/account,就像在我的情况下一样。那么:

PROJECT_ROOT = os.path.normpath(os.path.dirname(os.path.abspath(__file__)))

编辑...正确的方式:

好的,上面的代码在某种程度上可以工作,并且它直接设置了模板为所需的内容。但是一旦你包含社交应用程序,你就会开始遇到反向url错误,比如对于dropbox_login,你没有提供一个命名视图。

在阅读了Burhan Khalid在这个其他stackoverflow线程中的评论后,我最终发现以下内容可以正常工作:

'DIRS': [
    os.path.join(PROJECT_ROOT, 'templates', 'example'),
]

在我的情况下,在运行自git clone git://github.com/pennersr/django-allauth.gitexample应用时,在开发服务器上这将产生 /home/mike/example/example/templates/example
我将提供的bootstrap模板中的整个子目录accountsocialaccount复制到DIRS目录中。这与example应用程序从github获取的目录结构以及examplesettings.py文件中的说明完全相反。
您可以像example应用程序一样保留urls.py文件,只需简单地:
    url(r'^accounts/', include('allauth.urls')),  

4

在您的观点中:

from allauth.account.views import SignupView, LoginView


class MySignupView(SignupView):
    template_name = 'my_signup.html'


class MyLoginView(LoginView):
    template_name = 'my_login.html'

4
一旦你了解了Django的模板查找顺序,并根据需要正确配置TEMPLATE=[],就非常容易了。如果只是覆盖allauth的模板,那么无需对视图或Python代码进行更改。
首先让我们简单了解一下Django模板查找顺序。Django的模板查找顺序如下所示,所有这些都在项目的settings.py中配置:'Loader':提供使用模板加载器的选项,负责定位模板、加载它们并返回模板对象。一般实现不会太多地使用它。如果您没有配置模板加载器,则以下两个选项之一将决定视图使用哪个模板。'DIRS':在此处,您可以明确告诉Django按顺序从上到下搜索模板的位置。'APP_DIRS':如果将此字段设置为true,则Django会在您应用的目录中查找模板。要正确地使用此选项,您需要按照以下方式组织您的模板:
root_dir
 app1_dir
  templates
   your_template.html
 app2_dir
  templates
   your_template.html

你必须将模板文件夹命名为"templates",并且只有将模板放在该文件夹中才能起作用。
第三个选项有点奇怪,如果在应用程序的视图中找不到模板,则Django会遍历其他应用程序的模板目录来查找它。如果模板组织得当并且模板的命名约定标准化了,那么当本地应用程序的目录中找不到模板时,不应该在其他应用程序的目录中错误地找到该模板。好吧,您可能有一些场景希望以这种方式工作。 现在,回答您的问题: Allauth默认使用以下位置的模板:
Python installed directory or virtual env --> *Lib --> site-packages --> allauth --> templates*

通常情况下,您希望覆盖所有allauth的模板,因为它们非常基础,您希望美化/修改它们所有,以下是使您能够覆盖它们所有的步骤,如果您不希望覆盖它们所有,请按照以下方式操作,但不要更改该模板的HTML,简单明了!

假设您的项目结构如下:

projectdir
  app1_dir
  app2_dir
  projectname_dir

将模板目录从Python安装目录或虚拟环境--> Lib --> site-packages --> allauth --> templates复制到您选择的目录中,假设您选择将其保留在app1_dir中(您可以选择任何目录,没有区别,但应根据您的要求选择适当的目录),然后在app1_dir中创建一个名为“allauth”的目录(您可以随意命名它),然后将复制的allauth的模板目录粘贴到此目录中,因此现在您的项目结构如下所示:

projectdir
  app1_dir
    allauth
      templates
        account
        openid
        socialaccount
        base.html
  app2_dir
  projectname_dir

在项目设置中将TEMPLATES = []更改为以下内容:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'allauth', 'templates'),

                ],
        'APP_DIRS': True,
    },
]

这里的BASE_DIR是项目目录(根目录)

基本上,你可以将从allauth目录复制的模板目录保存在任何自己选择的项目目录中,但你必须确保在这里提供了正确的路径:

'DIRS': [os.path.join(BASE_DIR, 'allauth', 'templates')

如果仍然不行,那么请设置'APP_DIRS': False。这样,Django会显示一条调试信息,并且不再使用应用程序目录(即site-packages中的allauth目录)。通过查看该错误消息,您可以找出配置中的问题。

1
谢谢,你的解释非常好。 - Azur

2

对我来说只有一个解决方案:

首先将TEMPLATE_LOADERS设置为加载filesystem.Loader

TEMPLATE_LOADERS = [
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
    # 'django.template.loaders.eggs.Loader',
]

第二步 - 使用存储了来自allauth的模板的路径创建TEMPLATE_DIRS。确保您从allauth应用程序的模板文件夹中复制了完整的文件夹层次结构。

TEMPLATE_DIRS = [
    os.path.join(BASE_DIR, 'cms', 'templates', 'allauth'),
]

在这个例子中,我为我的应用程序创建了一个路径,命名为cms,因为这是我的项目的主要应用程序。接下来,您可以开始编辑base.html模板。

1
根据此处提供的文档,可以通过复制项目中模板基础位置内的目录结构来覆盖模板。例如,只需创建account/logout.html,就可以覆盖allauth提供的logout.html文件。在我的情况下,settings.py 如此设置。
TEMPLATES = [
   {
       'BACKEND': 'django.template.backends.django.DjangoTemplates',
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
   }
]

是的,这对我有用。文件为 templates/account/logout.html。 - user4292309
忘了说了...在Django 3.1.4上。 - user4292309
非常感谢!账户/部分对我有帮助。 - user3286381
文档链接已更改 https://docs.allauth.org/en/latest/common/templates.html - undefined

1
在Django v2.0中,我使用了这个方法并且它起作用了。遵循Django书籍[https://djangobook.com/mdj2-django-templates/]的指导。
重要的方法是使用[os.path.join(BASE_DIR, 'name_of_your_file/templates/allauth')]而不是使用'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'templates', 'allauth')],
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'name_of_your_file/templates/allauth')],
        'APP_DIRS': True,

这是我第一次在stackoverflow上发帖,我找了很久终于找到了这个解决方案,现在分享出来,希望能帮助到其他人。


1
我找到了一种更好的方法,但是忘记了。All Auth可以让您轻松完成此操作,但文档很少。这是我的下一个最简单的解决方案,直到我重新发现更广泛的方法。#lol
该代码创建了一个自定义登录页面,但模式很简单,易于复制。您可以将所有此代码放入urls.py中,也可以不放:
from allauth.account.views import LoginView


class Lvx(LoginView):
    # Login View eXtended

    # beware ordering and collisions on paths
    template_name = "components/login.html"

    # don't forget to create the login page, see All Auth docs
    # for use. /components is in your app templates path


login = Lvx.as_view()

urlpatterns = [
    url(r'^accounts/login/$', login),  # usually up top
    ...
]

还有一个设置可以用来指向自定义页面,稍后会进行编辑。欢迎反馈。


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