Django admin: every app with different custom base_site.html - django

Hi I have been trying to customize my admin page and I have some application specific admin pages that require custom javascript and css. I would like to have different base_site.html within the template/admin/ of each app including the required javascript and css. The thing is that only the changes of the base_site.html of the first registered app (inside the settings.py file) are shown.
Is my approach of customizing base_site.html for each app correct? if yes, how can I get it to work?
How to include css and js only in some admin pages?
Thank you.
-app1
-templates
-admin
-base_site.html
-app2
-templates
-admin
-base_site.html
-app3
-templates
-admin
-base_site.html
-manage.py

If you just want to add some custom javascript and css to your admin you'd better use ModelAdmin asset definitions. See django docs for more. Something like this:
class ArticleAdmin(admin.ModelAdmin):
class Media:
css = {
"all": ("my_styles.css",)
}
js = ("my_code.js",)
As for base_site.html, you will not be able to override it for each application, it is general template not application specific template. But anyways, you could override/extend change_form.html and change_list.html templates, based on each application or even for each model. And tree should be as follows:
-app1
-templates
-admin
-app1
-change_form.html
-change_list.html
And if you use extension rather than overriding you may access header using extrahead and extrastyle blocks.
/app1/templates/admin/app1/change_form.html
{% extends "admin/change_form.html" %}
{% block extrahead %}
{{ block.super }}
... your code here ...
{% endblock %}

Related

Can't figure out why django variables aren't passed into template

I've been working on this for a few hours and for the life me of I can't get a variable from my django app into a template.
html:
{% block content %}
{{test}}
{% endblock content %}
views:
def home(request):
context = {'test' : "test"}
return render(request, "/dbus/templates/index.html", context)
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name = 'home')
]
(note: I left the imports out of the view code sample I provided)
I think you dont need to add 'templates' in the argument "/dbus/templates/index.html"
If dbus is your django-app and templates is a folder inside this django-app, then by convention, you've to add a subfolder named dbus inside this templates folder.
All HTML files regarding the django-app 'dbus' should be stored inside this subfolder named 'dbus' (which comes inside templates folder)
The path of index.html should looks like: YourProjectFolder/dbus/templates/dbus/index.html
If you're right till this part, then you've to render the html page like "dbus/index.html"
You dont need to add that templates directory in the render argument.
So correct line is: return render(request, "dbus/index.html", context)
This should solve your problem!
Turn's out the issues was due to caching in either Nginx or uWSGI. I restarted both and the changes started working

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.

'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

ViewDoesNotExist while rendering

I have split up views.py into two files, organized thus:
views/
__init__.py
public.py
private.py
In one view (in public) I render a template which has the following:
<a href='{% url app.views.private.login_view %}'>Login</a>
I get the following error when loading the url:
TemplateSyntaxError at /
Caught ViewDoesNotExist while rendering:
Could not import app.views.private.app.views. Error was: No module
named app.views
What am I doing wrong?
Try naming your url and then using that name inside the {% url ... %} tag, like so:
#urls.py
url(r'^xyz/abc/$','app.views.private.login_view', name='login_view'),
#login_view.html (template-code)
<a href='{% url login_view %}'>Login</a>
I would recommend naming your url patterns, then using the name in the {% url %} tag.
Are you using {% load url from future %} ? If so you will need to put quotes around your url so that it is {% url 'app.views.private.login_view' %}
The release notes for Django 1.3 explains it.
https://docs.djangoproject.com/en/dev/releases/1.3/#changes-to-url-and-ssi