creating my own context processor in django - django

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.

Related

Django how to pass context or model objects in base.html without pass views in url

I know I can pass context using somethings like this in base.html
class MyViews(request):
#my code.....
context= {#my context}
return render(request, 'base.html', context)
then pass the views in url. But is there any to pass context in base.html without using url?? any idea?? I also tried this
'context_processors': [
...
# add a context processor
'my_app.context_processor.my_views',
], #getting this error No module named 'contact.context_processor'
You can use context_pro.py it will send context objects to all html files but I dont recommend it. because context pro send contexes all html files if you want to use. first open context_pro.py file
from .models import *
def funcName(request):
some = Some.objects.all()
anther_one = Another.objects.all().order_by('-date')[:16]
context = {
'some':some,
'anther_one':anther_one,
}
return context
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'yourApp.context_pro.funcName',
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

How to use a view function on all pages in Django?

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.

Can I not use django.contrib.contenttypes?

I'm using django 3.0.
I use django-admin startproject mysite and created a sample django project.
I don't think the sample project has any models so I commented out "django.contrib.contenttypes" in INSTALLED_APPS in settings.py. I also commented out all middlewares.
I then wrote a simple view
from django.shortcuts import render
def index(request):
return render(request, 'hello.html')
and hello.html is just a blank file.
Once I access the page, django throws exception
Model class django.contrib.contenttypes.models.ContentType doesn't
declare an explicit app_label and isn't in an application in
INSTALLED_APPS.
Can anyone help explain the exception? The sample project doesn't have any model, why do I need django.contrib.contenttypes? Can django websites live without django.contrib.contenttypes?
I have to remove django.contrib.auth.context_processors.auth in TEMPLATES.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [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',
],
},
},
]

Django base template location

I am creating a website using Django 2.0.7. I need to use a base template that is outside the purview of all applications, but can be inherited and used by templates in my other applications in the project.
I have edited my settings.py file appropriately (as per the documentation), but still when I go the root (i.e. home) page of my site, I get a blank page - can anyone explain why?
I have the following directory structure
myproj
----manage.py
----app1
----templates/
base.html
index.html
----static/
----myproj
__initi__.py
wsgi.py
settings.py
urls.py
views.py # <- I added this
The relevant parts of my settings.ini file looks like this:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['{0}/templates/'.format(BASE_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',
],
},
},
]
views.py:
from django.http import HttpResponse
def index(request):
return HttpResponse()
Why can't django find my index.html ?
Use 'DIRS': [os.path.join(BASE_DIR, "templates")] in your settings, and your view should return a object which knows what template to render, like this one:
from django.shortcuts import render
def index(request):
return render(request, 'index.html')
There's also TemplateResponse(), SimpleTemplateResponse() and other objects you can return, depending on your needs.

Passing an object in every Django page

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