Django template extends wrong template - django

I have multiple apps in my project:
app1/
templates/
base.html
some_template.html
app2/
templates/
base.html
overview/
index.html
app2/templates/overview.index.html has this code:
{% extends 'base.html' %}
So it should extend app2/templates/base.html
But in fact it extends app1/templates/base.html! Why and how to fix it?

The app template loader returns the first template that matches, it doesn't know that you are rendering a template 'inside' a specific app.
The Django docs recommend that you put your app's templates in myapp/templates/myapp, not myapp/templates/. This prevents the templates from clashing.
Now we might be able to get away with putting our templates directly in polls/templates (rather than creating another polls subdirectory), but it would actually be a bad idea. Django will choose the first template it finds whose name matches, and if you had a template with the same name in a different application, Django would be unable to distinguish between them. We need to be able to point Django at the right one, and the easiest way to ensure this is by namespacing them. That is, by putting those templates inside another directory named for the application itself.
So in your case, you would change the structure to
app1/
templates/
app1/
base.html
some_template.html
app2/
templates/
app2/
base.html
overview/
index.html
You would then have to update the template name in your view, e.g.
return render(request, 'app2/some_template.html', {})
and in your template
{% extends 'app2/base.html' %}

Why? Because that's how discovering of django templates works.
Django will search for templates in each app's templates dir (in order that apps are presented in INSTALLED_APPS) and in global templates dirs. First found template will be served. This allows one app to use templates from other. It also allows to change templates for one app by another. Without that there wouldn't be easy way to style your admin panel by your own.
How to fix it? Create subdirectory in templates in each of your apps and keep here app-specific templates. Of course you will have to access them by entering path like:
{% extends 'app2/base.html' %}

Related

Django Combine two templated from different apps

I have two apps with the following structure
project->
main app->
templates->
dashboard.html
my app->
templates->
mydashboard.html
I want to include mydashboard into dashboard, well this is possible using include template tag. but my problem appears when I have to pass some parameters into mydashboard, let's say they are named param1 and param2 these parameters are the variables which I have to load from my app app. well one possible method is to filling these params in dashboardview in mainapp and pass them using include tag into mydashboard.html like below
def user_dashboard(request):
...-->here I have to get data from my app (this view is in main app and I do not want to make main app be dependent to my app
return render(request, 'dashboard.html', {'param1': 0, 'param2': 34})
then in dashboard.html I add this part
{% is_app_installed "myapp" as is_myapp_installed %}
{% if is_myapp_installed %}
{% include "myappdashboard.html" with param1=param1 param2=param2 %}
{% endif %}
It seems the above method works but the main problem is that using this method mainapp is dependent to myapp and I do not want to this happens.
is there any other method to load those param1 and param2 inside myapp?
thanks
I can't see the details of the templates, but if you want to decouple the two templates I suggest you to rethink how you organise your templates logic. Try to rearrange the logic adding a base_dashboard.html in a common template dir with snippets and base templates to share between the apps.
Then the myappdashboard.html and dashboard.html can extend it with {% extend base_dashboard.html %}.

Django templates inheritance between apps

In Django templates there is extends tag used like {% extends "base.html" %}.
I want if possible to name templates in several apps the same (like templates/bookkeeping/bookkeeping.html).
I want the more specialized app (which handles bookkeeping for a particular project) to extend a template in a less specialized app (which handles common tasks for bookkeeping for several our projects) with extends. Particularly in the less specialized app I create a template without much design. In the more specialized app I want to present the same information but with a particular design (CSS, etc.)
What can be done about this in Django 1.11?
If it is impossible to use extends of a template with the same template name (but different app), what are other possible ways to solve the problem? I could check existence of derived.html and fall back to base.html if there is no derived.html, but this would lead to writing tedious Python code. Is there a better way?
Could you not just name the directories for the templates in each of the apps as following:
app1/templates/app1/bookkeeping/bookkeeping.html
app2/templates/app2/bookkeeping/bookkeeping.html
Then in the more specialised app (app2) extend by using:
{% extends "app1/bookkeeping/bookkeeping.html" %}
Or am I missing something here?
Edit:
You could link your Python code to point to one template, say templates/pages/bookeeping_base.html. In that template you could say:
{% if project.is_specialised %}
{% include 'app2/bookkeeping/bookkeeping.html' %}
{% else %}
{% include 'app1/bookkeeping/bookkeeping.html' %}
{% endif %}
Then as I described above, the app2 template could still extend the app1 template.

Use custom directory for "templatetags"

some one know if its likely use custom directory for "templatetags" eje: "my-project/templatetags"
Normal
My-Project-Name
My-App
__init__.py
templatetags
__init__.py
Need Some Like This
My-Project-Name
templatetags
__init__.py
This is possible. Just add location of your templatetags.py or templatetags directory to Django settings.py into OPTIONS in TEMPLATES setting.
In my case I put my templatetags in the libs/ directory that is located in project root dir.
You have two options, builtins or libraries:
TEMPLATES = [{
...
'OPTIONS': {
...
'builtins': [
'libs.templatetags'
],
# or as #x-yuri pointed out, you can put them in `libraries`
'libraries': {
'my_tags': 'libs.templatetags',
},
}
}]
If you use builtins, it is available everywhere and you don't need to use {% load %} for that.
If you use libraries you need to use {% load my_tags %}.
This is not possible. The reason being, templatetags must reside inside a django app.
From the documentation of templatetags:
Custom template tags and filters must live inside a Django app. If
they relate to an existing app it makes sense to bundle them there;
otherwise, you should create a new app to hold them.
The app should contain a templatetags directory, at the same level as
models.py, views.py, etc. If this doesn’t already exist, create it -
don’t forget the __init__.py file to ensure the directory is treated
as a Python package. After adding this module, you will need to
restart your server before you can use the tags or filters in
templates.

Difficulty overriding Django Admin template

I'm using Django 1.2.4 on Ubuntu 10.10. I'm trying to override the index.html template for the admin module. I've been following these instructions. I also looked at this question, but I'm still having difficulty.
The instructions say to create an admin directory in the templates directory:
templates/
admin/
index.html
I want to override a single block in the index.html. (Really, all I want to do is append some text to the end. Is there an easier way than copy/pasting the entire block and changing it?) (Update: Looks like {{block.super}} may help.)
To signal that I'm overriding, I put this at the top of my index.html:
{% extends "admin/index.html" %}
Of course, that results in a stack overflow (from the terminal):
Exception RuntimeError: 'maximum recursion depth exceeded in __subclasscheck__' in <type 'exceptions.RuntimeError'> ignored
What is the correct way to do this? I tried a symlink per an answer on the linked question, but that resulted in the following:
me#mycomp:~/foo$ sudo ln -s /usr/local/lib/python2.6/dist-packages/django/contrib/admin/templates/ django_admin
[sudo] password for me:
ln: creating symbolic link `django_admin': Protocol error
What am I doing wrong?
The recursion error is because you're extending the admin/index.html with itself.
You can either:
copy the entire admin/index.html template in your templates/admin/ directory, and it will replace the default template with yours
override the index.html per app or model, as explained here
I know this is late after the question, but you know, google traveling...
Amend settings.py with an extra template folder, for example:
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
"/home/mysite/webapps/django/myproject/templates",
"/home/mysite/webapps/django/lib/python2.7/django/", # extra folder
)
Then in myproject/templates/admin add your own index.html like:
{% extends "contrib/admin/templates/admin/index.html" %}
{% block branding %}
<h1 id="site-name">Administration for TheLittleButtonCo</h1>
{% endblock %}
Variations are possible, obviously. This works on Django 1.3.1 final
Not sure if you found the answer, but you need to change
{% extends "admin/index.html" %}
to
{% extends "admin/base_site.html" %}
as that is what the original index.html page overwrites. Because the Django system searches your templates folder before using the default admin one, so in this case it finds the admin/index.html in your templates, then it's trying to extend itself with the extend (hence the recursion error).
For reference you can customise the base_site.html in you templates too, it extends base.html. The best thing to do is copy the original from:
/usr/local/lib/python2.6/dist-packages/django/contrib/admin/templates/
and paste it into your templates folder as a starting point
I use an extra package, called django-smart-extends

Django template dir switching

Does anyone know a way to switch the TEMPLATE_DIR in django dynamically.
I need to create a set of templates for a mobile version and would like the templates to sit inside there own dir instead of inside the root template dir ie: I would like 2 template dirs 'templates' and 'mobile_templates' and not have to use 'templates/mobile' for the latter.
Do I have to write my own template loader?
You can set multiple template directories in your settings file and Django will search them in the order that you list them. Problem is that it doesn't care if you want template_x.html from directory a or b. If you have the same template_x in directory a and in b, it'll pull from which ever is listed first which can be confusing. A good way would be as follows:
Have only 1 template directory somewhere called 'templates'. Inside of this folder have a folder called 'mobile' and a template called 'default' (or whatever). Then when you call your template you just have to use the directory path as well.
In your view:
# some mobile view (everything omitted brevity)
get_template('mobile/some_template.html')
# some normal view (everything omitted brevity)
get_template('default/some_template.html')
In your templates:
Mobile Template:
{% extends 'mobile/base.html' %}
Normal Template:
{% extends 'default/base.html' %}
Settings File:
TEMPLATE_DIRS = (
'D:/some/path/to/templates',
)