Django unable to distinguish between template directory when extending - django

I have two apps, consisting of adminApp and mobileApp. Both have their own template directory and totally seperated. Unfortunately django keeps looking in the wrong directory when i eg. use extend, it looks into the first template directory according to the order in INSTALLED_APPS:
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
INSTALLED_APPS = (
...
'adminApp',
'mobileApp',
...
)
My directory structure is:
adminApp/
templates/
base.html
mobileApp/
templates/
base.html
So basically what happens is that when i have a file such as mobileApp/templates/pages/index.html with a {% extends "base.html" %} it uses adminApp/templates/base.html instead of its own.
How can i avoid this and keep them separated?

Your apps don't follow the Django conventions for template directories. The app name should be repeated to avoid this issue:
adminApp/
templates/
adminApp/
base.html
mobileApp/
templates/
mobileApp/
base.html
You can then unambiguously specify which template you wish to extend:
{% extends "mobileApp/base.html" %}

Related

Django display list items based on URL

I'm trying to hide/show sections of my navigation depending on my active URL.
I have attempted to do this using the re.match() method, but jinja did not like this. This code is in an HTML include file for my side navigation and is as follows:
<ul>
{% if bool(re.match('^/url/path', request.get_full_path)) %}
<li><a href='link1'>Link1</a></li>
<li><a href='link1'>Link2</a></li>
<li><a href='link1'>Link3</a></li>
{% endif %}
</ul>
Thanks in advance.
You can create a custom filter and use it. Something like this maybe;
# nav_active.py
import re
from django.template import Library
from django.core.urlresolvers import reverse
register = Library()
#register.filter()
def nav_active(request_path, search_path):
# WRITE YOUR LOGIC
return search_path in request_path
Inside the template
{% load nav_active %}
{% if request_path|nav_active:"/search/path" %}
....
{% endif %}
Update as per your comment. From Django docs code layout section for custom template tags and filters:
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.
So create a folder at same level as your view.py and name it templatetags. (Don't forget to add __init__.py inside). At the same level of that __init__.py add your nav_active.py and it should be ready to use. Like this:
yourapp/
__init__.py
models.py
views.py
templatetags/
__init__.py
nav_active.py

Two apps extend from the same base.html in Django

I have two apps. Both have different base.html templates that index.html extends from. The index.html is different though on each app.
But for some reason it only extends from the same app with base.html? How is this possible?
This is how it looks in both of my my index.html templates:
{% extends 'base.html' %}
How is your template/ directory structure set up? If an index.html template extends from base.html, Django will choose whatever base.html is in your root template directory.
Solution:
Either rename one of your base.html templates to something like base2.html and put it in templates/ alongside base1.html, or create new directories in templates/ to put the base.html files into.
For solution A, make sure you change {% extends base.html %} to {% extends base2.html %} in the appropriate index.html template.
For solution B, your base.html files would keep the same name, but be in different directories. So one is in say templates/base1/base.html and the other is in templates/base2/base.html. Your index.html files would extend like {% extends base1/base.html %} and {% extends base2/base.html %}. Note that all extension paths are relative to the root of your chosen template directory.
IMO solution B is better as it separates the code for each template base into different, explicitly named folders. Better organization/flexibility and less confusion for you in the future.

Django tables template not being found

In Django 1.7, I'm unable to provide a custom template. Instead it just defaults to the django_tables2/table.html
from django_tables2 import Table as BaseTable
class Table(BaseTable):
class Meta:
template = 'portal/base_table.html'
And my folder structure:
apps/portal/
├── __init__.py
├── tables.py
├── templates
│ └── portal
│ ├── base.html
│ ├── base_portal.html
│ ├── base_table.html
│ └── home.html
In the above, templates such as portal/base.html are resolved by template finders.
If I forego the Meta class and instead set:
from django_tables2 import Table as BaseTable
class Table(BaseTable):
template = 'portal/base_table.html'
I instead get the error TemplateDoesNotExist as it seems to be trying to resolve /data/www/apps/portal/templates/No template names provided among others.
To further support that I think the template should be resolving:
>>> render_to_response('portal/base_table.html')
<django.http.response.HttpResponse object at 0x7fa940c74690>
>>> render_to_response('portal/base_table.html2')
...
raise TemplateDoesNotExist(name)
TemplateDoesNotExist: portal/base_table.html2
My settings.py file contains:
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
path = lambda *a: os.path.join(BASE_DIR, *a)
TEMPLATE_DIRS = (
path('templates'),
)
This is working for all other templates such as for Views. Does django-tables2 not use the same lookup method?
In django tables2, for using custom template for providing custom template, you need to render it in templates like this:
<div class="">
{% load render_table from django_tables2 %}
{% render_table table 'portal/base_table.html'%}
</div>
You can check this answer as reference: Is it possible to apply a template tag to a <td> when using django-tables2?
As I ran into this Error with Django 1.8, and nobody seems to have the solution, for future reference this is how I solved it:
I had a manager that would be called as the default manager. This managers method get_queryset() was overwritten with a function to sort the resulting objects and return this list.
Turns out even though this is often seen in examples on the net and something similar is inside the documentation, you can only return a queryset there, not a list! Therefore just rename that function to anything else and you are allowed to return lists. Then you just call model.manager.anythingbutgetqueryset() and you are fine.
Add following setting to your settings.py file :-
TEMPLATE_DIRS = (
"path_to_your_template_directory",
)
Edit the path accordingly

'custom_filters' is not a valid tag library

I'm trying to create custom filters, and I've followed the steps in the Django documention.
However, when I load the template that loads the filters the following error is thrown:
'custom_filters' is not a valid tag library
...which refers to the line below in the template:
1 {% extends 'shared/base.html' %}
2 {% load custom_filters %} <--- the error
3
4 {% block title %}
5 Showing project {{project}}
6 {% endblock %}
The file structure:
project/
...
...
models.py
views.py
templates/
templatetags/
__init__.py
custom_filters.py
custom_filters.py:
from django import template
register = template.Library()
#register.filter(name='ownership')
def ownership(project, user):
return project.added_by_user == user
So, by some reason Django can't find the custom_filters file as it seems, even though I have done everything as one should (as far as I know).
What am I doing wrong?
NOTE: Of course I've tried to restart the server.
Template tags folder must be beside of templates folder, views.py, models.py, ...
//Don't forget also to put __init__.py outside the templatetags,
#register.simple_tag
def ownership(project, user):
return project.added_by_user == user
If your App name is MyApp and your tag folder name is templatetags then in settings.py you should have :
INSTALLED_APPS = [
'MyApp',
'MyApp.templatetags'
]
Both your app and your tag folder which is under your app package
Django Project are needed there.
-> MyApp
---> models.py
---> views.py
---> templatetags
-----> __init__.py
-----> app_filters.py

django include template from another app

While setting up my project and working to keep apps non-dependent, I've hit a snag. I'd like all of the templates from the different apps to have a consistent header and footer. Here's what I'm trying:
myproject/
base/
templates/
header.html
footer.html
app1/
templates/
my_app1_page.html -> want to include 'header.html'
and 'footer.html' from base app
Pretend there are many more apps that want to do this as well. Is this possible and/or the right way to do it?
As long as the apps are in INSTALLED_APPS and the template loader for apps dirs is enabled, you can include any template from another app, i.e.:
{% include "header.html" %}
... since your templates are located directly in the templates dir of your app.
Generally, in order to avoid name clashes it is better to use:
app1/
templates/
app1/
page1.html
page2.html
app2/
templates/
app2/
page1.html
page2.html
And {% include "app1/page1.html" %} or {% include "app2/page1.html" %} ...
But: for keeping a consistent look and feel, it is so much better to use template inheritance rather than inclusion. Template inheritance is one of the really good things of the Django template system, choose inheritance over inclusion whenever it makes sense (most of the time).
My recommendations:
Have a base template for your project ("base.html" is the default convention) with header and footer and a {%block content%} for your main content.
Have your other templates inherit form base.html {% extends "base.html" %} and override the content section
See another response to this question for links to the doc
While you can certainly do that by using the include tag and specifying absolute paths, the proper way to work in Django is by using Template inheritance.
If you start a project with "$ django-admin startproject project" a folder named "project-folder-name" i.e. project/ is created. After adding a few apps and adding the apps in the "settings.py" -> INSTALLED_APPS=[..., app1, app2] and creating a templates folder within the project/ I got structure like this:
project/
project/
templates/
base.html
app1/
templates/
app1/
page1.html
page2.html
app2/
templates/
app2/
page1.html
page2.html
in template app1/template/page1.html I wrote
{% extends 'base.html' %}
and the "TemplateDoesNotExist at /" Error message appeared.
Then I added another App named "core" and added base.html to the template folder (+edit INSTALLED_APPS in settings.py) and i got this structure now:
project/
project/
templates/ (unused)
base.html (not seen)
core/
templates/
base.html
app1/
templates/
app1/
page1.html
page2.html
[...]
Now the error message disappears and the base.html is found with templates/app1/page1.html:
{% extends 'base.html' %}
You can change the folder structure like this:
core/
templates/
core/
base.html
then you need to change the template app1/page1.html to
{% extends 'core/base.html' %}
as well.
As an alternative you can also add "your-project-name" in this explaination "project" into your settings file like this:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'project', # your project name main folder
'core',
'App1',
'App2',
]
And now django finds the project/templates/base.html as well. However I don't know if this solution is recommended.
project/
project/
templates/
base.html (now it is found)
P.S. Thanks (my upvotes aren't counted yet) and comment me if this answer was somehow clear and understandable