Allow multiple apps to use {% extend base.html %} in Django without clashing? - django

I have only started with Django recently, and assume there must be a good solution for this issue!
After installing django-allauth through pip, it tried to extend base.html from my project/templates folder rather than from its own subdirectory. This user had the same issue and was told to rename one of the base.html files and then update all references to it in the related app templates. For a complex app (already bad), this is error-prone; it's even worse if multiple third party apps are each defining their own base.html and referring to it simply as {% extends 'base.html' %}. Also, I think this only applies to third party apps, since I can easily name base.html something different for each of my own apps, but I don't want to mess around with 3rd party apps that work.
My question is: is there a safe/easy way to allow multiple third-party apps to use {% extends 'base.html' %} without clashing?
I have read the docs on template inheritance in Django and understand that:
By default, templates are loaded from the filesystem first, and then from app subdirectories. Therefore my projects/templates directory, which is defined in my TEMPLATE_DIRS setting, will be called first; hence the django-allauth problem.
I can reverse this order for the app subdirectory to be called first, by changing the order of TEMPLATE_LOADERS. However, this just means that my website will now extend the wrong base.html.
Although I can fix the current clash by renaming allauth's base.html as allauthbase.html and changing child template references to it as {% extends 'allauthbase.html' %}, this seems bulky.
Most wierdly, this person is complaining that each app extends its own base.html by default, but that seems impossible...

It seems there is an open issue related to the problem:
https://github.com/pennersr/django-allauth/issues/370

Related

How to use a base.html for default Wagtail Page instance?

Wagtail starts new projects with a single welcome template. However, this template does not inherit from any parent template, such as a base.html. In our project, we have previously defined a base.html containing global HTML tags and CSS/JavaScript includes.
How can we tell the default Wagtail Page model to display in a template that extends base.html?
To clarify, there are two possible setups, depending on how you create your project:
If you start a new project from scratch with wagtail start myproject, the initial migrations (which exist partly within Wagtail itself, and partly within the project template) will set you up with a HomePage model and an initial homepage. The template for this page type lives at home/templates/home_page.html, and is already set up to inherit from a base template (which lives at myproject/templates/base.html).
If you follow the documentation for integrating Wagtail into an existing Django project, the initial migrations (which in this case are entirely within Wagtail) will give you an initial page of type wagtailcore.Page. You're not really expected to use this page type directly (not least because it has no fields beyond the title, and no way of adding new ones) - it's only done this way because there are no "proper" page models set up yet, and there needs to be something as the initial state of the page tree. The idea is that once you've set up at least one page model within your app, you can create your real homepage, point the Site record at it (in Settings -> Sites), and delete the initial stub one.
Nevertheless, if you really want to give wagtailcore.Page a full-fledged template with a base template, you could create a template file inside one of your project's apps at the path templates/wagtailcore/page.html. As long as the app in question is above 'wagtail.core' in the INSTALLED_APPS list, this will override the barebones template supplied by Wagtail.
{% extends "base.html" %}
Add that to your template, it will extend anything in the base.
If your base template has blocks in it, you use the same syntax
{% block content %}
This will appear wherever you have this same block in the base.html template
{% endblock %}
Wagtail is built on top of Django, you can read more about its templating language here: https://docs.djangoproject.com/en/3.0/ref/templates/language/

Change django template search path depending on request

For my application I want to serve a different base.html (and other templates and static files) for visitors and for admins: visitors will see a customized themed frontend, admins will see the editor interface (not related to the django admin interface). Some templates / resources will be shared between the two frontends.
I know I can do this by having separate settings.py configurations and include different template paths in each of them through a django app, but that would also mean I have to run two instances of the app. I'd rather serve both frontends from a single instance (or pool of workers).
Is there a way to dynamically add extra folders to the Django search path? That should suit my needs: if the user comes through the visitor domain, search the added path first and then the defaults, else just use the default template search path.
This is exactly why I've created django_layers
It's inspired by the Plone skinning/layer system where you can switch skins and have the framework search different layers for templates, staticfiles, and so on. I was missing something similar in Django where, like you, the only option I could find was inheritance or distinct INSTALLED_APPS configurations.
It turns out it's also very suitable for other use-cases such as A/B testing.
The packages is relatively new, let me know if it works for you or if you have issues if you decide to use it.
You can leverage template inheritance for this purpose, especially the {% extends %} template tag, which can accept variables instead of literal strings.
Example:
In your child templates make them extend unknown base template like this:
{% extends BASE_SITE_TEMPLATE %}
{% block page_head %}
<!-- Custom per-page static files may be defined here -->
{% endblock %}
{% block page_content %}
...
{% endblock %}
And then write a template context processor that will pass the BASE_SITE_TEMPLATE variable based on your custom conditions to rendered templates:
def base_site_template(request):
# Here goes your conditions to select proper base template, for example
# by checking request.user permissions or some other logic.
...
return {'BASE_SITE_TEMPLATE': ...}
Of course You will need to define various base templates, like base_site_user.html, base_site_editor.html, base_site_admin.html.
This method doesn't require you to change any of your views, just child templates, so I think it's one of the simplest methods to do what You want.

django accessing template block through custom templatetags

I've started working on a django project that has couple apps that are used entirely through templatetags through other apps. Voting app, comments app..etc
Although am faced with a challenge when it comes to rendering assets for that particular templatetag (css,js).
I already have a base.html with blocks for css and js but how would I be able to access them using templatetags to append related assets. Currently am heavily relying on inclusion templates and I did a lot of research and it seems impossible to touch blocks.
any advise? even if I would change the approach of using blocks am open to any suggestion
it seems perfectly reasonable to tell the users of your library (app) that they must include your css/js somewhere in their template. E.g. django crispy-forms does this. Just give them some sample code to include in their base template

How to conditionally skin an existing site (for partner branding)

I've got an existing Django site, with a largish variety of templates in use. We've agreed to offer a custom-skinned version of our site for use by one of our partners, who want the visual design to harmonize with their own website. This will be on a separate URL (which we can determine), using a subset of the functionality and data from our main site.
So my question is: what's the best way to add reskin functionality to my site, without duplicating a lot of code or templates?
As I see it, there are several components which need to work together:
URL: need to have a different set of URLs which points to the partner-branded version of the site, but which can contain all the standard path info the site needs to build pages.
Template 'extends': need to have the templates extend a different base, like {% extends 'partner.html' %} instead of {% extends 'base.html' %}
View logic: need to let the views know when this is the partner-branded version, so they can change the business logic appropriately
My idea so far is to put the partner site on a subdomain, then use a middleware to parse the domain name and add 'partner' and 'partner_template' variables to the request object. Thus, I can access request.partner inside my views, to handle business logic. Then, I have to edit all my templates to look like this:
{% extends request.partner_template|default:'base.html' %}
(According to this answer, 'extends' takes a variable just like any other template tag.)
Will this work properly? Is there a better way?
If you are using different settings.py for the different sites you can
specifiy different template loading directories. (Which may default to your unskinned pages.)
Personally I'm not convinced by having different business logic in the same view code, that smells like a hack to me - the same as extensive conditional compilation does in C.
So to sum up.
Use django.contrib.sites and different settings.py
Get a clear idea, how much this is a new app/website using the same data, or just different css/templates.

template django

how can i use different template in different application.in a project i have two app 1)Site 2)Ad .I want to use default template in Ad but different in Site..How to ?OR in the template is there is a way to use 'if condition' as i have to change only two lines in the templates.
First of all, you are never bound to use same template in different application. Different apps can use different templates, as common practice these days are to place template directories in respective app folder.
Moreover, for change of two lines, you can alwayz use `
{% if condition %}
something
{% else %}
some other thing
{% endif %}
or
{% ifequal var 'var' %}
something
{% else %}
some other thing
{% endifequal %}
All in same template.
Edit
If you say you want to use same templates in diff applications, you can apply path of template considering the facts that,
firstly django template loader will look for a template in same app directory,
then in projects's root directory, and if not found, it will look for it django's own template source.
So if you want to use template anywhere, you can place them in a folder called templates, placed in the same path where your apps directories are. (i.e. root of the project).
projectroot/app1/templates/app1.html
projectroot/app2/templates/app2.html
projectroot/app3/
projectroot/templates/common.html
likewise common.html can be available to all apps.
Use template inheritance http://www.djangobook.com/en/1.0/chapter04/ Define a base template and change only the desired block.
Pl. check the links to the question I had raised for which the answer is provided by Yuji T
How to use 2 different change_list.html for 2 applications in the same django project