What is a context in Django? - 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']}

Related

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.

Getting value of URL-encoded request.GET variable in Django Template

I am using Django 1.3 with Python 2.7.2 on Windows 7 x64.
I have a URL pattern like this:
url(r'^(?P<club_id>\d+)/$', 'view_club')
From the pattern I want to be able to use request.GET in my templates to be able to create URLs to my views based on this GET variable (club_id). I have read online that I would be able to do:
{{ request.GET.club_id }}
However, this is always showing up as blank. I cannot figure out the reason why. I have the request context processor in my list of default context processors.
Thanks for the help.
In your example, club_id is not a GET parameter, it is part of the path in the URL. Your view function takes club_id as an argument, it should then put it in the context so the template can access it.
For example, your view function:
def view_club(request, club_id):
return render(request, "template_name.html", { 'club_id': club_id })
then in your template:
{{ club_id }}
IF you are passing an variable in the URL - in this case club_id - simply include it as an argument in your view function next to request:
def get_club(request,club_id):
club = Club.object.get(pk=club_id)
return render_to_response('club.html', {'club': club})
now in your template you can access {{club}} as the individually selected object and do things like {{club.name}} This also works for variables with multiple objects which you would use a for loop to iterate through.

Accessing global variable in view using context processor in 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)?

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>)

Django tags and filters in Lift?

This is a generalization of my previous question about pluralize filter:
Does lift have an equivalent of Django's tags and filters?
Tags are small piece of predefined code that can be used directly in html template, for example:
{% now "jS F Y H:i" %}
renders the time right now in the given format.
Filters
Filters operate (in html template) on the context variables in the template, for example:
{{ value|capfirst }}
if called on a value "john" will result in "John". Or:
{{ value|length }}
will render the length of the string into the template.
As you can see the filters operate on the context variables that are passed to the template.
Considering tags, you could define those yourself with snippets.
As snippet is basically a callback much as a Django tag is. You don’t get any easier syntax, though, because Lift’s templates are pure XML/Html.
<Lift:Tag.now format="jS F Y H:i" />
And the logic would be defined in
class Tag {
def now: NodeSeq = // ...
}
Filtering is something you generally can’t do in a Lift template because Lift doesn’t allow any variables in a template. The whole concept is thus inapplicable. (You could do XML transforms or or bind magic but that would be a bit too much for a simple value.length.)
No, if you need the length of some value in your Html, you will have to define that inside the snippet and expose it.
If you really can’t live without filters in your template (though I can assure you, it is a good thing to separate all HTML template and code and it works once you are used to it), have a look at Scalate which may be used together with Lift as well.
This kind of logic should be in the render method of a snippet. Display code in pure Scala (rather than in a template language hybrid) is a first-class citizen with respect to testing, IDE's and refactoring tools.
These kinds of transforms don't come built-in, but you can add them with implicits:
class HappyString(s: String) {
def capfirst = ....
}
implicit def toHappyString(s: String) = new HappyString(s)
Then call these in your render method before binding whatever value it is you're generating.