18

Answers in other questions leave impression that this is in fact very easy:

However, I can't get it to work at all.

From example app settings I can see that django-allauth supposedly expects it's templates to be in account, openid and socialaccount directories. But when I put template at TEMPLATE_DIR/account/signup.html it doesn't get loaded, signup view displays template bundled with django-allauth. What do I miss?

Community
  • 1
  • 1
Red
  • 1,450
  • 2
  • 17
  • 33

9 Answers9

24

I eventually resorted to loading my app before django-allauth. In settings.py:

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

This solution goes against what's presented in example app, but I was not able to solve it in other way.

Red
  • 1,450
  • 2
  • 17
  • 33
  • It works, but as you said doesn't seem the best way. I think allauth should have a config var in setting to specify the path of all templates. – miguelfg Aug 11 '14 at 15:45
  • Thanks for this - and as you say @miguelfg it works - but it doesn't seem right at all. Did either of you ever work out a better way? – awidgery Feb 04 '15 at 17:46
  • @awidgery in allauth 0.18 template overriding works for me regardless of app loading precedence. I simply put my templates in right directories and they get loaded before default ones. – Red Apr 11 '15 at 08:41
  • This is still the only solution that worked for me w/ Django 1.11.5 & django-allauth 0.33.0. And @Red is right - it isn't mentioned in the documentation. – trubliphone Oct 13 '17 at 07:44
7

Adding a template directory for allauth in template dirs will do the trick. In Django 1.8 his can be done by editing template dir settingsTEMPLATES as follows.

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

I think below code will work on other versions of django

TEMPLATE_DIRS = [
    os.path.join(BASE_DIR, 'templates'),
    os.path.join(BASE_DIR, 'templates', 'allauth'),
]
bignose
  • 30,281
  • 14
  • 77
  • 110
cutteeth
  • 2,148
  • 3
  • 25
  • 45
  • One small correction. I was trying the same and the custom allauth templates were not being hit. The reason was my templates were in `rootDir/templates/allauth/templates`. So two changes were required. (1) - Add `APP_DIRS : True` to template `TEMPLATE_DIRS`, (2) -- copy the `account/` to `allauth` folder or use `os.path.join(BASE_DIR,'templates', 'allauth', 'templates')` – pravin May 12 '18 at 13:50
7

To this day--- we're now on Django-1.10.5--- the django-allauth docs remain most unhelpful on this score. It does seem to be that Django looks in the templates directory of the first app listed, the setting of DIRS in TEMPLATES in settings.py notwithstanding. I'm providing an answer only to help you implement Adam Starrh's answer, to help with the reverse urls (I got errors until I took care of those).

In your urls.py file put:

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'),
]

Presently the views.py file is here, so you can extend the above to other templates.

I must add that you still need in TEMPLATES, something like:

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

And in this example that would be if your templates are in /templates/bootstrap/allauth/account, which they are in my case. And:

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

EDIT... THE PROPER WAY:

OK, the above works, to a point, and it's good that it directly sets the template to what you want. But as soon as you include social apps you'll start to get reverse url errors such as for dropbox_login, for which you have not provided a named view.

After reading Burhan Khalid's comment on this other stackoverflow thread that the questioner found, I eventually found that the following works:

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

And this yields /home/mike/example/example/templates/example on the development server in my case, as I am running the example app from git clone git://github.com/pennersr/django-allauth.git.

Into that dir of DIRS I copied the entire subdirectories account and socialaccount from the provided sample bootstrap templates. This is utterly contrary to the directory structure of example as it comes from github and to notes in the settings.py file of example.

And you leave urls.py just as in the example app, with simply:

    url(r'^accounts/', include('allauth.urls')),  
Community
  • 1
  • 1
Mike O'Connor
  • 2,494
  • 1
  • 15
  • 17
4

In your views:

from allauth.account.views import SignupView, LoginView


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


class MyLoginView(LoginView):
    template_name = 'my_login.html'
Adam Starrh
  • 6,428
  • 8
  • 50
  • 89
2

For me only one solution works:

first make TEMPLATE_LOADERS to load filesystem.Loader

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

second - make TEMPLATE_DIRS with path where you copied templates from allauth. Make sure you copied full folder hierarchy from templates folder of allauth app.

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

in this example a made path to my app, named cms because this is the main app of my project after you could start to edit base.html template

bignose
  • 30,281
  • 14
  • 77
  • 110
Stavinsky
  • 323
  • 4
  • 11
2

It's quite easy once you know Django's template look up order and you configure the TEMPLATE =[] properly as per your need. There's no need to play with views or Python code if it's just about overriding allauth's templates.

Let's understand the Django's template look up order at first, just a little. Django's template lookup order is as follows, all of these are configured inside TEMPLATE =[]in project's settings.py.

I. 'Loader': Give you the option to use Template Loaders which are responsible for locating templates, loading them, and returning Template objects. General implementations don't use it much. If you haven't configured a template loader then one of the following two option would decide which template is used by your view.

II. 'DIRS': Here you get the option to explicitly tell Django where to search for templates, in order, up to down.

III. 'APP_DIRS': If this field is set to true then Django looks for your template in your apps' dir. To correctly use this option you need to organize your templates as follows:

root_dir
 app1_dir
  templates
   your_template.html
 app2_dir
  templates
   your_template.html

You must name your templates dir as "templates" and you must put your templates in that dir only for this to work

Third option is little weird though, if a template in your app's view isn't found in corresponding app's template dir Django will go through template dir of other apps to find it. It works well if templates are organized properly and naming convention of templates is standardized, so that when a template isn't found in local app's dir, that template shouldn't be erroneously found in other app's dir. Well, you may have some scenarios where you would want it to work that way.

Now, to the point answer to your question: Allauth by default uses the templates from:

Python installed directory or virtual env --> *Lib --> site-packages --> allauth --> templates*

You would usually want to override all the allauth's templates as they are very basic and you would want to beautify/modify them all, following are the steps which would enable you to override them all, if you don't wish to override all of them do as follows, but just don't change the HTML for that template, simple!

Suppose your project structure is as follows:

projectdir
  app1_dir
  app2_dir
  projectname_dir

Copy the templates dir from Python installed directory or virtual env --> Lib --> site-packages --> allauth --> templates to a dir of your choice, suppose you chose to keep it in app1_dir (you may chose any dir, makes no difference, but you should choose an appropriate one as per your requirements), then create a dir in app1_dir named 'allauth' (you could name it anything you like), then paste the copied allauth's templates dir in this dir, so now your project structure would look as follows:

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

Change your TEMPLATES = [] in project settings as follows:

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

                ],
        'APP_DIRS': True,
    },
]

Here BASE_DIR is projectdir (root dir)

Basically you may keep the copied template dir from allauth dir in any project's dir of your choice, but you must enusre that you provided the correct path here:

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

If it doesn't work then, set 'APP_DIRS': False, then you would see a debug message from Django and it wouldn't use app dir (allauth dir in site-packages). And then looking at that error you may figure out what's wrong with your config.

Vivek Singh
  • 346
  • 3
  • 14
1

I found a better way to do this but forgot. All Auth allows you to do this very easy but and low on documentation. Here is my next easiest solution, until I rediscover the vaster way. #lol

The code creates a custom login page but the pattern is simple and easy to replicate. You can put all this code in urls.py, or not:

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
    ...
]

There is also a setting you can use to point to a custom page, will edit this at some point. Feedback welcome.

Marc
  • 1,895
  • 18
  • 25
1

As per the documentation provided here, it is possible to override the templates by replicating the directory structure inside the template base location of your project. For instance, by just creating the account/logout.html , I was able to override the logout.html file provided by allauth. The settings.py in my case is stated here

TEMPLATES = [
   {
       'BACKEND': 'django.template.backends.django.DjangoTemplates',
       'DIRS': [os.path.join(BASE_DIR, 'templates')],
   }
]
sudo97
  • 904
  • 2
  • 11
  • 22
1

In django v2.0. I use this method and its works. By following the django book, [https://djangobook.com/mdj2-django-templates/] .

The important way is to use [os.path.join(BASE_DIR, 'name_of_your_file/templates/allauth')] instead of using '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,

This is my first time post at stackoverflow yah,i find this solution long time and finally its work so i share it, hope can help someone.

Bryan
  • 11
  • 1