I have an object called Groups that is used in every single page on my website. However, Django only passes in Python objects to html through render_to_response and I can't render to response everytime something happens to the groups object.
How do I maintain this object(as in make it respond to adding and deletion) and produce it in every Django template that I have without calling render_to_response?
write a template context processor:
#my_context_processors.py
def include_groups(request):
#perform your logic to create your list of groups
groups = []
return {'groups':groups}
then add it in your settings file:
#settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"path.to.my_context_processors.include_groups",
)
now a variable groups will be available to you in all your templates
If you need data added to more than one template contexts you should look into achieving that via your own template context processor.
You need to create template context processor to pass an object to each request. Here is some example
#tu_context_processor.py
from setting.models import Business
def include_business(request):
business = Business.objects.all().last()
return {'business': business}
in your settings file:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATE_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',
'core.tu_context_processor.include_business',
],
},
},
]
now a variable business will be available to you in all your templates
tested in Django 4
Related
I'm building an app in Django in which I have a layout where I have the navbar and I extend this layout to each page.
In order to have the navbar to receive the proper variables from the view I have to write the same code on each view. There has to be a way to write this code once and affect directly the layout so I won't need to type it multiple times but I haven't found the answer.
How can I write the function one time? Something like a global variable in Django I guess.
I hope I managed to explain myself ok, thanks in advance!
first you create context_processors.py somewher in your app.
then you write the function needed, something like:
from .models imoprt Somemodel
def alltimefunc(request):
something = Somemodel.objects.all()
return something
finally you add it in the settings.py
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',
'your_app_name.context_processors.alltimefunc', #here
],
},
},
]
Here comes context processors handy in these kind of situations. You can write a function and register it with template engine in settings.py file. This way you can write code once and it will affect directly to the layout.
What is the standard, preferred way to make settings available to templates in Django 1.8? Currently, I define a custom context processor in my project and then reference it in my TEMPLATES OPTIONS setting. I've looked through the docs but didn't find this issue mentioned. This previous Stackoverflow question says to do what I'm doing but it's over two years old and I'm wondering if there's a newer preferred method. If I've learned one thing from recently upgrading Django, it's to do things the way the framework wants you to do them. You'll have fewer problems this way.
Thanks.
# utils/context_processors.py
from profile.models import UserProxy
from conf.settings import base as base_settings
def global_constants(request):
"""Constants that are available to all templates."""
return {
'site_name': base_settings.SITE_NAME,
'media_url': base_settings.MEDIA_URL
}
# myproject/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug', # default
'django.template.context_processors.request', # default
'django.contrib.auth.context_processors.auth', # default
'django.contrib.messages.context_processors.messages', # default
'utils.context_processors.global_constants', # project
],
},
},
]
I have come to a point where I need to pass certain variables to all of my views (mostly custom authentication type variables).
I was told writing my own context processor was the best way to do this, but I am having some issues.
My settings file looks like this
TEMPLATE_CONTEXT_PROCESSORS = (
"django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.contrib.messages.context_processors.messages",
"sandbox.context_processors.say_hello",
)
As you can see, I have a module called 'context_processors' and a function within that called 'say_hello'.
Which looks like
def say_hello(request):
return {
'say_hello':"Hello",
}
Am I right to assume I can now do the following within my views?
{{ say_hello }}
Right now, this renders to nothing in my template.
My view looks like
from django.shortcuts import render_to_response
def test(request):
return render_to_response("test.html")
The context processor you have written should work. The problem is in your view.
Are you positive that your view is being rendered with RequestContext?
For example:
def test_view(request):
return render_to_response('template.html')
The view above will not use the context processors listed in TEMPLATE_CONTEXT_PROCESSORS. Make sure you are supplying a RequestContext like so:
def test_view(request):
return render_to_response('template.html', context_instance=RequestContext(request))
According to the django docs you can use render as a shortcut instead of render_to_response with the context_instance argument:
Alternatively, use the render() shortcut which is the same as a call to render_to_response() with a context_instance argument that forces the use of a RequestContext.
Let's say you have a file structure like this:
YourDjangoProject
├───project
│ ├───__init__.py
│ ├───asgi.py
│ ├───settings.py
│ ├───urls.py
│ └───wsgi.py
├───.env
├───manage.py
└───db.sqlite3
1) Anywhere, create a context_processors.py file
I'll create one in the project folder (with settings.py):
YourDjangoProject
└───project
├───...
└───context_processors.py
2) Create a function in context_processors.py that accepts a HttpRequest object as an argument and returns a dictionary
A context processor is just a function that accepts an HttpRequest object as an argument and returns a dictionary.
Like this:
# project/context_processors.py
def site_email(request):
return {'site_email': 'example#gmail.com'}
3) Add this to your context_processors setting in settings.py (at the bottom for security reasons)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'config' / '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',
'project.context_processors.site_email', # <- New context processor here
],
},
},
]
Now you'll be able to access the 'site_email' template variable on every single django template across your whole site.
Happy coding!
Since Django 1.8 you register your custom context processors like this:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
'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',
'www.context_processors.instance',
],
},
},
]
assuming your context processor is in app www in context_processors.py
If you’re using Django’s render_to_response() shortcut to populate a template with the contents of a dictionary, your template will be passed a Context instance by default (not a RequestContext). To use a RequestContext in your template rendering, use the render() shortcut which is the same as a call to render_to_response() with a context_instance argument that forces the use of a RequestContext.
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
},
},
},
]
I've enabled the django request processor
TEMPLATE_PROCESSORS = (
"django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.request",
)
Still i don't have to request variable available in templates.
I've to manually pass it. Using django 1.0.2
Everywhere on web it seems it's only about enabled request processor..
Also i am using RequestContext as :
return render_to_response(
'profile.html',
{
'persons':Person.objects.all(),
'person':Person.objects.get(id=id),
'request':request,
},
context_instance=RequestContext(request)
)
no luck
ohh darn
the new name for that is TEMPLATE_CONTEXT_PROCESSORS
settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
# ...
'django.core.context_processors.request',
# ...
)
TEMPLATE_CONTEXT_PROCESSORS
instead of
TEMPLATE_PROCESSORS
Be advised that as of Django 1.8, this has changed to a "TEMPLATES" setting, and in the default configuration, the request processor is NOT included.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
# insert your TEMPLATE_DIRS here
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
# Insert your TEMPLATE_CONTEXT_PROCESSORS here or use this
# list if you haven't customized them:
'django.contrib.auth.context_processors.auth',
'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',
],
},
},]
Just add the request processor back in to fix the issue:
'django.core.context_processors.request',
For more info, see the Django Upgrading Docs.
Are you sure you don't have the request variable available to the template? What happens when you remove the line
'request':request,
that's different from when that line is present. If your template loads the same either way, the problem is with your template.
MIDDLEWARE_CLASSES=(
...
'yourfolder.yourfile.yourclass',
...
yourclass:
class AddRequestToTemplate:
process_templaet_response(self, request, response):
response.context_data['request']=request