django admin: custom app_index with context - python

In django admin, we can define custom templates per app. In this case, I'm customising the app_index.html template for my application.
I'd like to add a few graphs and other to that page. Now that I've overridden the template, how can I override the corresponding view method?
I thought about making a custom AdminSite and override the app_index() (see https://github.com/django/django/blob/master/django/contrib/admin/sites.py#L511) method, but I have more than one application in my django installation, all of which will have a custom app_index.html.
What's the best way to add context to the app_index.html template?

Don't know if this is the best way, but it can be done with template
tags. Here is how I did it:
# <app>/templatetags/erp.py
register = template.Library()
#register.assignment_tag
def erp_get_tasks ():
return Task.objects.exclude (done=True).order_by ('priority')
.
# <app>/templates/admin/erp/app_index.html
{% extends "admin/app_index.html" %}
{% load erp %}
...
{% block footer %}
{% erp_get_tasks as tasks %}
{% for task in tasks %}
...

Related

Override django change_form.html template when a third app is overriding it

I am trying to override change_form.html only for one model, so I did as explained in the django documentation and created /templates/my_app_name/my_model_name/change_form.html.
The problem is, it is not working and I am not seeing the extra features that I have added to the change_form template. I am using django_guardian, which also overrides the same template, so my assumption is that this is causing the issue. It is worth mentioning, that before placing the template in the my_app_name/my_model_name/ folder, the features of both templates were visible in the admin interface.
Is there a way to apply this only for 1 model?
You should check this answer.
You can specify which template to extend in your template.
So you're extending third app's template which extends djando admin's template.
Example:
admin.py
class MyModel(ThirdAppModelAdmin):
change_form_template = 'my_app_name/templates/change_form.html'
my_app_name/templates/change_form.html
{% extends "thirdapp/templates/change_form.html" %}
{% block thatYouNeed %}
{{ block.super }}
Your content here
{% endblock %}
Well, at least this is how I managed to do that.
The GuardedModelAdmin changes change_form_template to use the template from django-guardian. Try changing it back in your model admin class:
class MyModelAdmin(GuardedModelAdmin):
...
change_form_template = 'my_app_name/my_model_name/change_form.html'

Django template tags forloop

I have created a template tag and trying to loop through the results from the template tag
but I don't get any results
tags.py
from django import template
from loadprograms import dbcontext
register = template.Library()
#register.simple_tag
def get_category():
x = dbcontext.DBContext()
results = x.executequery("Select name from Categories")
categories = [each[0] for each in results]
return categories
template code
{% load category_tags %}
{% get_category %}
{% for each in get_category %}
{{ each }}
{% endfor %}
The {% get_category %} prints all the categories without any issues but the for loop stmt
that loop through the results does not work
What could be the problem?
To make this change in your tag, you'll have to set a variable in the context, but if your objective is to have a list of categories available in templates, just like you would have passed it in from the view - then you need to write a template context processor, which will allow all views to have this variable in their context.
A template context processor is just a method that adds to the request context, by returning a dictionary. Think of it like a view function, that just returns a context.
from .models import Categories
def cat_names(request):
return {'category_names': Category.objects.values_list('name', flat=True)}
To activate this context processor, you have to do a few things:
Add the above code to a file called template_processors.py in the same place as your models.py and views.py.
In your settings.py, add the fully-qualified name of the method to the TEMPLATE_CONTEXT_PROCESSORS setting, making sure you don't override the defaults. To do this easily, import the default settings first, then add to it:
from django.conf.default_settings import TEMPLATE_CONTEXT_PROCESSORS as TCP
TEMPLATE_CONTEXT_PROCESSORS = TCP + ('yourapp.template_processors.cat_names',)
Use the render shortcut, which will make sure the context is correctly passed.
In your views, you can now just do this:
from django.shortcuts import render
def home(request):
return render(request, 'home.html')
In your home.html, you can now do:
{% for name in category_names %}
{{ name }}
{% endfor %}

Getting admin email(s) from Django template

Is there a way to access the ADMINS variable of the settings module from an any arbitrary template without adding manually adding it into the context before being rendered, similar to how request is available in any template using RequestContext if django.core.context_processors.request is in TEMPLATE_CONTEXT_PROCESSORS?
You can write your own context processor (which is a regular function that has request as parameter):
from django.conf import settings
def admin_emails(request):
return { 'ADMINS': settings.ADMINS }
and add path.to.my.context_processor.admin_emails to TEMPLATE_CONTEXT_PROCESSORS.
I'd use a template tag like discussed for this question:
Can I access constants in settings.py from templates in Django?
Specifically I use the code from this answer: https://stackoverflow.com/a/6343321/2250326
With that you can get at the AMDINS in your templates like this:
{% value_from_settings "ADMINS" as admins %}
{% for admin in admins %}
Name: {{ admin.0 }}<br />
Email: {{ admin.1 }}
{% endfor %}

Flask and jinja2 include tag

How to do it "include tag" in jinja2. I need to output a block of articles in the base template. And they work in children.
views.py
Articles.query.filter_by(name=name).first()
base.html
{% block content %}
Content base
{% endblock %}
---{{ this_articles_tag }}----
children.html
{% extends 'base.html' %}
{% block content %}
Content children
{% endblock %}
---{{ output Articles }}----
Django in this "include tag", how to do it in jinja2? (Without using context_processor)
If you need to include another template in the template, just use include in Jinja. But if you are talking about template tags (in Django I remember I liked them a lot), then in Flask only your mentioned context_processor is the way to go. Which I think is not a bad thing at all.
Edit:
Easiest way to get context processor registered as a function is pointed in the documentation.
But if you want something more fancy, like dynamic loader or you will load your functrion from different places, then you can define your own decorator function, which basically wraps the function which returns dictionary:
def example_templatetag():
def get_something():
return get_want_you_want_from_db()
return dict(get_something=get_something)
Then where you create your Flask app object you can easily register this function:
app.context_processor(example_templatetag)
And then in a template you can use is like:
{% set data_you_wanted=get_something() %}
{{ data_you_wanted }}
But maybe for you the way mentioned in documentation will be more than enough ;)

Django flatpages

I am using Django flatpages and would like to implement some logic in a template based on a user session variable.
eg.
{% if session.my_var %}
YES
{% else %}
NO
{% endif %}
Problem is that session object is not defined in flatpage context.
Create a TEMPLATE_CONTEXT_PROCESSOR which is then used by the RequestContext (see docs).
def session(request):
return { 'session': request.session }

Categories

Resources