Accessing "request" object within Jinja2 "environment" function - django

I am currently working on a project which heavily uses Jinja2 for template rendering. The relevant code looks like this:
settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [os.path.join(BASE_DIR, 'templates'),
os.path.join(BASE_DIR, 'request/templates'),
os.path.join(BASE_DIR, 'core/templates'),
os.path.join(BASE_DIR, 'vaux/templates')],
'APP_DIRS': True,
'OPTIONS': {
'environment': 'myapp.jinja2.environment',
'extensions': ['jinja2.ext.i18n', 'jinja2.ext.do', 'vcom.jinja2.blockcache', 'jinja2.ext.with_'],
'autoescape': False,
'bytecode_cache': FileSystemBytecodeCache(CACHE_DIR),
'auto_reload': True,
'lstrip_blocks': True,
'trim_blocks': True,
},
},
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages'
],
},
},
]
myapp/jinja2.py file looks like this:
def environment(**options):
env = Environment(**options)
env.globals.update({
'some_global_context_var': 'Some value'
})
# how do I access request ? So that I can write something like request.META['HTTP_HOST']
So my goal now is to try to get access to the request object, so that I can write something like request.META['HTTP_HOST']. Is there any way to do that ?
Prior to this, I tried to come up with a global context var using Django's vanilla `context processors' concept, but with Jinja2 it is not so easy.

You can access request from globals as documented in Django templates Jinja2 documentation
The default configuration is purposefully kept to a minimum. If a
template is rendered with a request (e.g. when using render()), the
Jinja2 backend adds the globals request, csrf_input, and csrf_token to
the context. Apart from that, this backend doesn’t create a
Django-flavored environment. It doesn’t know about Django filters and
tags. In order to use Django-specific APIs, you must configure them
into the environment

Related

How to set the templates directory in Django?

How to define a directory for storing all templates of my app? I am having a hard time finding the explanation how to set templates directory in Django settings.py file.
To set your path to templates folder you need to set your DIRS key with the value in which you are giving your path to templates as shown in the example below where at first i am setting a variable TEMPLATES_DIR where BASE_DIR give me the path to the folder where my manage.py is being kept and i concatinate projects directory alongwith templates directory because in my case i kept it inside project directory.
For example :-
TEMPLATES_DIR = os.path.join(BASE_DIR, 'project','templates')
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATES_DIR,],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
So, Here's the explaination What i did is set the TEMPLATES_DIR variable with reference to base directory that will take the path to folder where manage.py of your django project is being kept now i am concatinating the projects and templates directory just to navigate the exact folder structure that you kept for your templates in your project.
I hope you found this helpful. if you have any more doubts i'll be happy to answer those also.
Happy Coding. :-)
The way to set your templates directory in Django is by setting the value of the 'DIRS' key in TEMPLATES inside the settings.py like so (assuming it is present just inside your base directory (BASE_DIR):
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
In Django 3, the templates directory can be added to 'DIRS' like this as well:
'DIRS': [str(BASE_DIR.joinpath('templates'))]

Django context processor constants work in dev but not in production

I have a context processor which makes constants available in templates, including base template.
On my vagrant development server, using runserver, these work fine. The production server uses apache and WSGI.
I'm using Django 1.9.4 on both development and production.
This is the context_processors.py
from .constants import *
def template_constants(request):
return {'collection_name': COLLECTION_NAME,
'website_name': WEBSITE_NAME,}
This is from settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.request',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
'myapp.photos.context_processors.template_constants',
],
},
},
]
Constants are just in a file constants.py in my app, which I import into files which use them. The file has lines such as:
WEBSITE_NAME = "website name"
My views use render which should be including RequestContext
return render(request, 'page.html', template_variables)
I get no error messages, the variables simply don't have a value in the templates on production, so nothing is shown.
Apart from deployment, the code on production and dev is exactly the same.
Things I've tried:
- Adding string value directly into context_processors.py file (eliminating it being a potential issue importing variables from constants.py)
- Going back to Django 1.8 and 1.7 to check if it's something related to a specific version
None of these changes made any difference.

Can’t rename “Django administration"

I am working with Django 1.8.4 (latest).
I’m stuck with the official Django tutorial steps from: https://docs.djangoproject.com/en/1.8/intro/tutorial02/#customize-the-admin-look-and-feel
I am trying to rename “Django administration" but nothing happens.
I searched for the answer and found the totally same question here: _http://stackoverflow.com/questions/28787823/cant-change-django-admin-template There is now answer.
I did exactly the same as described there and in the tutorial.
As you can see from my repo: https://github.com/legobillyjoe/django-tutorial
the location of my base_site.html is mysite/templates/admin, as suggested in the tutorial.
I have added in settings TEMPLATES = [os.path.join(BASE_DIR, 'templates')], but nothing changes.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Any suggestions what I can do in order to make it work?
Did you run the makemessages command after you changed the translation strings? Also the default will only appear if the variables return None types
But actually, there's no need to override any templates for your requirement, in your admin file after your import statements add the following:
admin.site.site_header = _(u"Title")
admin.site.index_title = _(u"Subtitle")
So you have something like
from django.contrib import admin
from django.utils.translation import ugettext as _
admin.site.site_header = _(u"Title")
admin.site.index_title = _(u"Subtitle")
class FooAdmin(admin.ModelAdmin):
etc...

Why didn't this code in settings.py override the default Django project template?

I'm going through the very basic tutorial here and I am using my own base_site.html template instead of the default one, which has a different header text.
I copied the default template into my template folder, modified it, then linked the new template in settings.py:
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
No dice.
When I went a much simpler route and instead simply linked it with the single line below, it worked easily:
TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates/')]
Which is great! But now I want to know why the original code doesn't work.
If it helps, my folder structure is:
- Scripts
- mysite
- mysite
- polls
- templates
- admin
base_site.html
The TEMPLATES setting will be introduced in the django 1.8. It is unavailable in the current django 1.7.
So read the tutorial for the actual version of django you using.

Load a Django template tag library for all views by default

I have a small typography related templatetag library that I use on almost every page. Right now I need to load it for each template using
{% load nbsp %}
Is there a way to load it "globally" for all views and templates at once? Putting the load tag into a base template doesn't work.
There is an add_to_builtins method in django.template.loader. Just pass it the name of your templatetags module (as a string).
from django.template.loader import add_to_builtins
add_to_builtins('myapp.templatetags.mytagslib')
Now mytagslib is available automatically in any template.
It will change with Django 1.9 release.
Since 1.9, correct approach will be configuring template tags and filters under builtins key of OPTIONS - see the example below:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'builtins': ['myapp.builtins'],
},
},
]
Details:
https://docs.djangoproject.com/en/dev/releases/1.9/#django-template-base-add-to-builtins-is-removed
In django 1.7 just replace for from django.template.base import add_to_builtins
In Django 1.9 there is an libraries dictionary of labels and dotted Python paths of template tag modules to register with the template engine. This can be used to add new libraries or provide alternate labels for existing ones.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
'libraries': { # Adding this section should work around the issue.
'custom_tags' : 'myapp.templatetags.custom_tags',#to add new tags module.
'i18n' : 'myapp.templatetags.custom_i18n', #to replace exsiting tags modile
},
},
},
]