Accessing global variable in view using context processor in Django - django

Assuming I have a context processor:
def title(request):
return {'titles': 'mytitle'}
I can access this variable in template as {{ titles }}.
But how can I do so in a view?
def myview(request):
print request.titles
doesn't seem to work - 'WSGIRequest' object has no attribute 'titles'
Or maybe there is a better approach (than context processors) to have global variables accessible in both views and templates?
Thanks in advance.

Add your context processor method path (folder.context_processor.application_context) to TEMPLATE_CONTEXT_PROCESSORS.
in my case application_context is the method which i defined inside file context_processor.py
and method "application_context" returns {'titles': 'mytitle'}
if you want to use "title" as global variable in views use it in this way
global_var = RequestContext(request).get("app_config")
titles = global_var.get("titles")
print titles
The only advantage is "Same variable 'titles' will be visible for templates and also in your views"

Context processors aren't in any way global variables. They are simply functions that are run when a RequestContext is initiated, which add items to that context. So they're only available wherever you have a RequestContext, ie in a template.
Your examples don't really give a good idea of what variables you're looking to access. If it's just some constants you want to use everywhere, a good way is to define them somewhere central, say in settings.py, and import that module wherever you need it - plus use a context processor to add them to the context.

If you need the data in your views, it's cleaner to use Middleware in conjunction with a Context Processor:
Create a trivial custom middleware to store some data on the request object, say at request.x (example). Now you can access this in your views directly.
Enable django.core.context_processors.request in your TEMPLATE_CONTEXT_PROCESSORS to have request.x accessible from your templates.
See my related question: Django: How to provide context to all views (not templates)?

Related

django add context based on request to all views

I need to render my site without navbar if there is an argument in the request like nv=false and I want to pass a variable to context based on this so that the main template shows the block or not. my site also has lots of json-rpc functions, and I don't want to add extra overhead on it. how can I do this without rewriting all my views? (they are not class based and my site uses django 1.8)
Just add context processor that will add this variable to context. Context processor is a simple python function
def navbar(request):
return {'navbar_enabled': request.GET.get('nv', False)
and add it to the list of template context processors
TEMPLATE_CONTEXT_PROCESSORS = (
...
'MODULE_NAME.navbar',
...
)

What is a context in Django?

I'm trying to understand the concept of context and context processor.
What is a context and why do you use it?
Is a context a value you need to have available in order to use in a template?
Is a context and a context processor the same?
When you use a Django Template, it is compiled once (and only once) and stored for future use, as an optimization. A template can have variable names in double curly braces, such as
{{ myvar1 }} and {{ myvar2 }}.
A Context is a dictionary with variable names as the key and their values as the value. Hence, if your context for the above template looks like: {myvar1: 101, myvar2: 102}, when you pass this context to the template render method, {{ myvar1 }} would be replaced with 101 and {{ myvar2 }} with 102 in your template. This is a simplistic example, but really a Context object is the context in which the template is being rendered.
As for a ContextProcessor, that is a slightly advanced concept. You can have in your settings.py file listed a few Context Processors which take in an HttpRequest object and return a dictionary (similar to the Context object above). The dictionary (context) returned by the Context Processor is merged into the context passed in by you (the user) by Django.
A use case for a Context Processor is when you always want to insert certain variables inside your template (for example the location of the user could be a candidate). Instead of writing code to insert it in each view, you could simply write a context processor for it and add it to the TEMPLATE_CONTEXT_PROCESSORS settings in settings.py.
Hope this makes sense. Thanks for taking the class!
A context is a variable name -> variable value mapping that is passed to a template.
Context processors let you specify a number of variables that get set in each context automatically – without you having to specify the variables in each render() call.
The Context is described quite well in the official documentation. In short:
In day-to-day use, mostly indirectly, because helper functions construct the Context for you
See 1.: you only need it if you use the low-level api
No, a context processor is a function that takes a request and returns a dictionary of variables that are then available in all templates that are rendered with a RequestContext, for example:
def get_stuff_from_session(request):
return {'stuff': request.session['stuff']}

How can I pass a variable to all the HttpResponse?

I am learning Django and I want to list in all my pages the categories, that are for example categories = Category.objects.all(), but I think it's very redundant to declare that variable in all my views and pass it in every HttpResponse. Is there any way to do it for all?
If you want to add categories to all the pages it may be useful to write a custom template tag, https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags

Passing variables to a function

I have a module with a view function named 'edit' and a function named 'handle_upload'.
I would like to pass two variable values, which are available in the edit function, to the handle_upload function, but I don't know how, since I don't call the handle_upload function in the view function, so I can't pass the values as parameters.
For clarity:
# my_module.py
def edit():
dynamic variable #1
dynamic variable #2
render_to_response(some_site.html, locals(), context_instance = RequestContext(request))
def handle_upload():
# here is where I would want to get both variables.
It seems to me you want the variables to be available in two separate requests to the django server - first you want to set them when the user goes to the edit view, then you want to retrieve them in another view that calls handle_upload.
There are two options here, depending on the actual data you want to pass.
Pass it to the template and add it as hidden fields in the edit form.
This might be the easiest way, but be careful with sensitive data. If you don't want malicious users to see (and even edit) this data, don't do this. Users can and will edit the hidden html fields if they have bad intentions. Don't rely on this information to be correct if it can compromise the safety of your server.
First I'd like to advise you to use render instead of render_to_response, as the latter is outdated and will soon be deprecated. render ensures you have a RequestContext object, and requires the first argument to be the actual request object:
render(request, 'some_site.html', locals())
Then in your template, inside the form:
<input type='hidden' name='name1' value='{{ dynamic_variable_1 }}' />
<input type='hidden' name='name2' value='{{ dynamic_variable_2 }}' />
Then use request.POST.get('name1') to get the value of dynamic_variable_1 etc.
Use session middleware.
This way the data will stay on the server, and will even remain to be a Python object, so this handles every kind of object (I think, not 100% sure on that).
First, ensure 'django.contrib.sessions.middleware.SessionMiddleware' is in your MIDDLEWARE_CLASSES in your settings.py. It is by default if you used Django's startapp command.
Then, do the following in edit:
request.session['name1'] = dynamic_variable1
request.session['name2'] = dynamic_variable2
Then in the view that calls handle_upload, simply do the following and pass the variables to handle_upload:
dynamic_variable1 = request.session['name1']
dynamic_variable2 = request.session['name2']
You could go for something like:
dynamic variable #1
dynamic variable #2
def edit():
global dynamic variable #1, dynamic variable #2
render_to_response(… )
def handle_upload():
global dynamic variable #1, dynamic variable #2
#…
But be carefull with global variables if you are multithreading. If you do so consider a lock ;-)
You have two options.
declare your two variables global using the global keyword
have handle_upload take two arguments, and pass the two variables in
If you aren't calling it from edit(), that means you would need to return the two variables from edit() to the call site, and then pass them into handle_upload() from there.

Database localization in Django

I am using .mo files for localization in Django.
Also, in my database, I store some translated text in different fields, such as:
name_en, name_es, name_de (they are all columns in each row).
What will be the best method to choose the correct field inside a template?
i.e.:
{{ name.some_method }} will generate the correct translation based on the current localization.
Thanks,
Meit
You should look at http://goodcode.io/articles/django-multilanguage/ Here’s a simple solution that may fit your use case and is easy to implement and understand.
You should look at Django Transmeta, it work the same way as what you've done (DB fields with language code) but it's a more complete solution. It already deal with the template stuff, etc.
You can check Model Internationalization and Django Packages for more info and ideas in this domain.
I can see two method for doing this, one in your view and the other one is in the template...
In view:
Probably you keep the user language information somewhere so,
user_lang = 'es'
obj = Somemodel.objects.get(pk=123434)
obj.local_name = getattr(obj, 'name_%s'%user_lang)
So, you keep local translation in a specific variable of the instance and in your template you can use is as:
{{obj.local_name}}
But that might be costly if you wish to pass the template a queryset instead of a single instance. For a such usege you have to evaluate that value for each object in your queryset.
In template:
That is a more complex way of solving the porblem in the template...
Define a template tag and pass object_id, and local language information and get the translated text using a similar getattr function. But in that point, if you wish to use this for more than one model, you probably have to pass a content type information for your template tag too, such as:
{% get_translation <object_id> <content_type_id> <local_language> %}
And in your template tag function, do something like:
from django.contrib.contenttypes.models import ContentType
....
cont_obj = Content_type.objects.get_for_id(<cotent_type_id>) #get the related model
obj = cont_obj.get_object_for_this_type(pk=<object_id>) # get your object
return getattr(obj, 'name_%s'%<local_language>)