Can't get Jinja2 working with django 1.9 - django

If I install as suggested in django 1.9 docs (https://docs.djangoproject.com/en/1.9/topics/templates/#django.template.backends.jinja2.Jinja2)
with two items in TEMPLATES, the first is the jinja2 backend, the second is the django backend:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [
PROJECT_ROOT+ "/templates/jinja",
],
'APP_DIRS' : True,
'OPTIONS': {
'environment': 'commshub.jinja2_settings.environment',
},
},
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
PROJECT_ROOT+ "/templates",
],
'OPTIONS': {
'debug': DEBUG,
'context_processors': [
"django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.media",
'django.core.context_processors.request',
'django.core.context_processors.static',
'django.contrib.messages.context_processors.messages',
],
},
},
]
but WITHOUT 'environment' setting, then appears to work provided I remove also 'auto_reload' setting for both jinja and django, otherwise get
__init__() got an unexpected keyword argument 'auto_reload'
If I add myproj.jinja2.py with content as shown in django docs, still no 'environment' option, I get:
cannot import name Environment
If I change "from jinja2 import Environment" to ""from jinja2.environment import Environment"
No module named environment
In light of this post, https://groups.google.com/forum/#!msg/django-users/pytjLOVUwmM/gbiDmswSuq4J, I try renaming jinja2.py to jinja2_settings.py and add this TEMPLATE options:
'environment': 'jinja2_settings.environment', -> pop() takes no arguments (2 given)
'environment': 'myproj.jinja2_settings.environment', -> No module named commshub.jinja2_settings
Tried removing django backend altogether but got the same error as above.
Not sure what else to try!

Related

Accessing "request" object within Jinja2 "environment" function

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

Django context processors model not found

I am trying to implement a context_processor in Django via a custom app. I am failing due to Module not found error.
My app name is brand.
My context processer looks like this:
from .models import ContactDetail
def contact(request):
contact = ContactDetail.objects.first()
return { 'contact' : contact }
My app is included in installed apps and the model has been migrated.
I have included my context processor into the context_processors list as per documentation:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'mysite', 'templates'),],
'OPTIONS': {
'context_processors': [
'brand.context_processors.contact',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.i18n',
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.template.context_processors.media',
'django.template.context_processors.csrf',
'django.template.context_processors.tz',
'sekizai.context_processors.sekizai',
'django.template.context_processors.static',
'cms.context_processors.cms_settings',
],
'loaders': [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
'django.template.loaders.eggs.Loader'
],
},
},
]
The Error I am getting is:
Django Version: 1.11.16
Exception Type: ModuleNotFoundError
Exception Value: No module named 'brand.context_processors'
I have tried searching for solutions but most of the questions are for previous versions of django ( <= 1.8 ) I am using 1.11.16.
I have read through the docs and it is unclear what I am missing.
Any help is apreciated.
Make sure that you named that file context_processors.py and placed in myapp directory.

Setting up http error custom pages in django

I wanted to add custom error pages to my website, butI am getting the simple pages, for example the 403 error I am not getting the template I built. template is located in templates/http_errors/ folder.
my template settings in settings file looks like this:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [normpath(join(PROJECT_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',
'django.template.context_processors.media',
'django.template.context_processors.i18n'
],
},
},
]
and urls.py:
from django.conf.urls import handler403
handler403 = 'core.views.custom_handler403'
and views.py:
def custom_handler403(request):
response = render_to_response('http_errors/HTTP403.html', {},
context_instance=RequestContext(request))
response.status_code = 403
return response
I tried a lot of options found on django docs and stackoverflow but could not still find the answer. It would be great if you helped me with this.
P.S. I am using Django 1.10 and Python 3.5
These custom pages will only work if you have DEBUG = False in your settings. Otherwise normal debug handlers will be used

Django throws error message "'loaders' option is empty"

I'm trying to move to the new Django 1.8 settings with regard to templates, and am getting following error message:
Django couldn't find any templates because your 'loaders' option is empty!
Here is my TEMPLATES setting:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
],
'OPTIONS': {
'context_processors': [
'django.contrib.auth.context_processors.auth',
],
},
},
]
"Loaders" also needs to be specified in TEMPLATES if not specified as TEMPLATE_LOADERS:
'loaders': [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
],
The alternative is to specify 'APP_DIRS': True,.
See https://docs.djangoproject.com/en/1.8/ref/templates/upgrading/

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
},
},
},
]