Django display list items based on URL - django

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

Related

Django admin: every app with different custom base_site.html

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 %}

'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

Adapt a view if an app is installed with Django

I have a web app with a project that works alone (it's index, login.. pages).
I would need to change the index page if a new app is installed (e.g: add a link, a table in the template with my app models..). Have it dynamic.
The removal of the app must let the project intact and just remove the link.
How can I do that? Is it possible?
You can use the Django's application registry:
In [1]: from django.apps import apps
In [2]: apps.is_installed("django.contrib.admin")
Out[2]: True
An application can actually be enabled by using a dotted Python path to either its package or the application's configuration class (preferred). Simply checking if "app_name" is in settings.INSTALLED_APPS will fail in the latter case.
def my_view(request):
from django.conf import settings
app_installed = 'app_name' in settings.INSTALLED_APPS
return render_to_response(template_name, {'app_installed': app_installed})
template:
{% if app_installed %}
...
{% endif %}
Or use a custom context processor.
In installed_apps.py
from django.conf import settings
def installed_apps(request):
return {
'app_installed' : 'app_name' in settings.INSTALLED_APPS
}
In settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
...
'installed_apps.installed_apps'
)
simple_tag version:
The tricky part is that you can't pass arguments to your simple_tag when it's used in a conditional. Therefor, you create a new variable specifically for your installed app with as is_myapp_installed.
In templatetags/my_filters.py:
from django import template
register = template.Library()
#register.simple_tag
def is_app_installed(app):
from django.apps import apps
return apps.is_installed(app)
In template:
{% load my_filters %}
...
{% is_app_installed "myapp" as is_myapp_installed %}
{% if is_myapp_installed %}
...
{% endif %}

Template Filter crashing

I have a template filter that I am loading in my template.
The template is in:
- userprofile/
- templatetags/
- __init__.py
- extras.py
Userprofile is in my installed apps and it seems to be importing extras correctly.
My template tag in extras.py is:
register = template.Library()
#register.filter
def minutes_seconds(seconds):
"""
Format a time in seconds in the MM:SS form.
"""
return '{:02}:{:02}'.format(int(seconds) / 60, int(seconds) % 60)
And in my django template I am doing:
{% extends 'base.html' %}
{% load extras %}
...
{{ items|minutes_seconds }}
But this blows up, and I get a TemplateSyntaxError: Invalid Filter. It seems to be a very low level error, because I can cause other errors in the template (for example, removing a {% for %} tag so it would otherwise raise an error), but it seems to be triggering this TempalteSyntaxError almost before the page is even rendered. What is going wrong here?
Check the dir "userprofile/templatetags/", are there compiled python files for init.py and extras.py?
If there are no compiled files in there then it means that templatetags dir is not being accessed by python. Make sure init.py file is there in that dir then restart the server and again check for .pyc files.