Override wagtail BaseSiteSetting template - python

I've been trying for some time to override the edit.html template for a single BaseSiteSetting in wagtail.
I'm not sure if this is even possible. My overrides for ModelAdmin templates are working just fine by using the following directory structure:
ModelAdmin index.html override
Is the same possible for my setting? Which is located in my success_stories app models.
I've looked through the wagtail/contrib/settings/templates/wagtailsettings/edit.html file but it's unclear to me how to do this. I've always worked with headless wagtail and don't have a lot of experience with templates.
The wagtail docs only seem to mention ModelAdmin overrides.

This would be done via standard Django template overrides: The first template that matches wins the cake.
In your case the template for the Wagtail Settings contrib module is located under templates/wagtailsettings/edit.html which means that in your app's template directory you have to make the exact same setup:
<you_app_directory>/templates/wagtailsettings/edit.html
Then depending on how you have setup your template discovery and/or have setup your app loading order one of the above templates will match first. So in order for your template to be the first one to match you can do two things:
Alter the loading order of your apps and make sure that your app comes before the wagtail.contrib.settings in your INSTALLED_APPS Django settings listing:
INSTALLED_APPS = [
...
<your_app>,
wagtail.contrib.settings
...
]
Or you can alter how templates are discovered by Django by changing the TEMPLATES setting:
TEMPLATES = [
{
...
'DIRS': [BASE_DIR / 'templates'],
"APP_DIRS": True,
...
},
]
Notice that DIRS comes before APP_DIRS, the order here matters as well. First Django will look in the directories you specify in DIRS, if nothing matched it will continue to look in the installed application directories.
Note that with the latter method BASE_DIR / 'templates' is a single templates directory at the root of your project.
Usually, if overriding third-party templates, the first method is used.

Related

Overriding a template in Django

I'm using this library to add a sessions tab on my django project. I'm calling the module's template from my project using this line:
<li>Sessions</li>
It works, but now I'd like to style the page, and to do that I need to override the module's template with my own template. So, as the module says here, I inherited the module's SessionListView on my own views.py to overrode the template:
from user_sessions.views import SessionListView
class MySessionList(SessionListView):
template_name = 'user_sessions/session_list.html'
Then I added the url to my urls.py
url(
regex=r'^account/sessions/$',
view=MySessionList.as_view(),
name='sessions',
),
And then I created my template on my own project which is located like this:
templates/user_sessions/session_list.
But for some reason, I still can't see MY template appearing, the module's template keeps appearing instead. Can anyone help me finding what I'm doing wrong?
The SessionListView already uses user_sessions/session_list.html by default, so your custom view isn't required.
It sounds like Django is finding the user_sessions/session_list.html template in the user_sessions app before your template. If your template is in an app's templates directory, then you can fix this by moving your app above user_sessions in your INSTALLED_APPS setting.
Alternatively, if you move your template to a directory in the 'DIRS' list in the TEMPLATES setting, then Django will find your template before it checks the app templates directories. This is cleaner if your overridden template doesn't really belong to any of your apps, and another advantage is that you don't have to re-order the INSTALLED_APPS list.
See the docs on overriding templates for more information.

Importance of apps orders in INSTALLED_APPS

Is the order of apps in INSTALLED_APPS important? I ask it because I have settings folder with two settings files: base.py and production.py and I put all my settings in base.py and then in production.py, I have:
from base import *
and then I override some settings.
Also in my base.py, I make INSTALLED_APPS a list, not a tuple. Because I want to remove some apps for production settings.
In production.py I want to write:
NOT_USED_APPS = ['debut_toolbar', 'other_odd_app',]
INSTALLED_APPS = list(set(INSTALLED_APPS) - set(NOT_USED_APPS))
In this case, the order of apps in INSTALLED_APPS is not like in base.py
Yes, the order is quite important.
From Django official docs on INSTALLED_APPS settings:
When several applications provide different versions of the same
resource (template, static file, management command, translation), the
application listed first in INSTALLED_APPS has precedence.
Example-1 Templates:
django.template.loaders.app_directories.Loader
If this template loader is enabled in your DjangoTemplates backend in the TEMPLATES setting or if you have passed it as a loaders argument to Engine, then it loads templates from Django apps on the filesystem.
For each app in INSTALLED_APPS, the loader looks for a templates subdirectory. If the directory exists, Django will look for templates in there.
Lets say in my project, i have defined INSTALLED_APPS as:
INSTALLED_APPS = ('myproject.app1', 'myproject.app2')
Now, i want to get the template some_template.html. Then get_template('some_template.html') will look for some_template.html in these directories, in this order:
/path/to/myproject/app1/templates/ # checks here first
/path/to/myproject/app2/templates/ # Then checks here
It will then use the one which it finds first.
Quoting from that section:
The order of INSTALLED_APPS is significant!
Example-2: Translations
Django applies the following algorithm for discovering translations:
The directories listed in LOCALE_PATHS have the highest precedence, with the ones appearing first having higher precedence than the ones appearing later.
Then, it looks for and uses if it exists a locale directory in each of the installed apps listed in INSTALLED_APPS. The ones appearing first have higher precedence than the ones appearing later.
Finally, the Django-provided base translation in django/conf/locale is used as a fallback.
We can see that order is important here also.
Example-3 Management Commands:
From Django 1.7 release notes on management commands and order of INSTALLED_APPS:
When several applications provide management commands with the same
name, Django loads the command from the application that comes first
in INSTALLED_APPS. Previous versions loaded the command from the
application that came last.
This brings discovery of management commands in line with other parts
of Django that rely on the order of INSTALLED_APPS, such as static
files, templates, and translations.
I experimented a bit and found two other things that I deemed useful to know:
The order in INSTALLED_APPS doesn't seem to effect when the models are created. Django figures out that certain models depend on others and run them in the correct order.
The apps ready method in the AppConfig object seems to run in the order they appear in INSTALLED_APPS.

How do I define custom filters for minimal use of django templates?

I have a python project that I'm using Django templates for to generate C++ source code.
I picked Django because the template language is quite restrictive and has a very large community making it easy for end-use developers to use and get help with.
I'm failing to add custom filters for my project (to translate one set of type names into another) because I have not done the normal django setup.
Instead:
from django.template import Context, Template
import django
if not django.conf.settings.configured : django.conf.settings.configure()
django.setup()
Lets me use Django templates perfectly but not define custom filters.
My custom filter is called ctypes_filters.py and I reference it in the template as
{% load ctypes_filters %}
Running my generation script results in the following error:
django.template.base.TemplateSyntaxError: 'ctypes_filters' is not a valid tag library: Template library ctypes_filters not found, tried
django.templatetags.ctypes_filters
How can I get django to find the filter without setting up a full Django project (database definitions etc)?
I know that other templating solutions are available (and are probably more light-weight) but I'm really keen to use Django's simple and elegant templates.
The location of Django template tags is done by convention rather than a configuration setting (see the code layout section of the template tags docs).
Put the ctypes_filter.py in a templatetags directory in an installed app (I've called it myapp here). Add an empty __init__.py to both the myapp and templatetags directories. The app doesn't need any other files you might commonly find in a Django app, like models.py or views.py.
myapp/
__init__.py
templatetags/
__init__.py
ctypes_filter.py
Then include myapp in your INSTALLED_APPS when configuring your settings.
django.conf.settings.configure(
INSTALLED_APPS=('myapp',),
)

django auth: password change template customization

I want to theme django auth's password change templates to my site. The problem is that django is seeing the django/contrib/admin/templates/registration/ versions of the templates instead of my beautifully crafted myapp/template/registration/password*.html.
This poster was told to fiddle with app order in settings.py, which is a bit fragile to my taste. I think this poster may have gotten a reasonable answer, but if so, I haven't quite understood it yet.
So what I did was to add a bunch of non-DRY cruft to my urls.py file, copied from auth_urls.py:
# Provide explicit templates where I've provided them, shadowing the URL's
# that registration.backends.defaults.urls will provide.
url(r'^accounts/password/change/$',
auth_views.password_change,
{'post_change_redirect': reverse_lazy('auth_password_change_done'),
'template_name': 'registration/password/change_form.html' },
name='auth_password_change'),
# ...
url(r'^accounts/', include('registration.backends.default.urls')),
This works, but saddens me in its repetition. Surely django encourages something cleaner. Any pointers?
(Fwiw, django 1.7 and python 3.4.2.)
Put this template into your project's templates dir and add the following code to the settings.py.
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, 'templates'),
)
By default django.template.loaders.filesystem.Loader is placed before django.template.loaders.app_directories.Loader in TEMPLATE_LOADERS so project's templates directory has precedence over app's templates.

Flask-Admin (python) - Having trouble overriding templates

I am attempting to utilize Flask-Admin for an administrative interface to my web service.
I have it working, but the theme does not match what the rest of my site uses. The documentation here suggests that it is as simple as overriding the master template, but when I do that I end up with circular reference errors.
I have also tried on individual templates by copying the templates from the install directory to my application structure, but I cannot figure out the path they use. It is like it just defaults to the install directory, even if I have templates of the same name local to my flask app. From the docs: "You can override any used template in your Flask application by creating template with same name and relative path in your main templates directory."... yet I am not able to do that. Does it still expect admin/ in front of the templates?
Does anyone have an example? I basically need to override the bootstrap theme used, but some other customization could be nice. I'm new to flask, and python for that matter, so this may be quite simple...
You will still need to place your templates in the admin sub-folder of templates:
yourapp/
app.py
templates/
master.html # <-- This will not override admin/master
admin/
master.html # <-- This one, however, will :-)

Categories