Accessing request.META.SERVER_NAME in template - django

I call a template like this from my view:
return render_to_response('mytemplate.html', context_instance=RequestContext(request))
I'm trying to access the hostname of my current server (in this case, localhost), but it just prints blank when I place {{request.META.SERVER_NAME}} in the template.
In my settings.py file, I don't have any TEMPLATE_CONTEXT_PROCESSORS defined. I'm not sure if I need to specify anything there, or if that could solve the problem.

You have to add the request context processor to have it added to the template context automatically. Or you could explicitly add the request to the context dictionary render_to_response('foo', {'request': request})
https://docs.djangoproject.com/en/dev/ref/templates/api/#django-core-context-processors-request
Note that if you add the request context processor, you should remember to add the defaults as well.

Related

Django admin without template context processor

Is it possible to make django-admin interface not to include some of the template context processors?
in settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
..some.django.context.processors,
'myapp.views.context_processor',
)
in my.views.py:
def context_processor(request):
return {'user': my_custom_string}
So, data returning in 'my' context_processor overrides 'user' variable in django-admin template context and i've got an error.
And the second problem is that 'my' context_processor returnes 'fat' dict. There is no need to have it in admin's interface
You have the request object available to your context processor; you can examine the request's path to see if it's under the root path of the admin.

Access request in django custom template tags, using the tag decorator

There is a question with the same title and problem: Access request in django custom template tags
The solution proposed, for instance pass takes_context = True to the decorator works perfectly well for tag helpers (simple_tag, inclusion_tag and assignment_tag) but not with the low-level tag decorator.
#register.tag(takes_context=True)
def mytag(parser, token):
...
raises the exception :
tag() got an unexpected keyword argument 'takes_context'
2 questions :
is there a reason why the tag decorator does accept the takes_context argument ?
how can I access the template context with this decorator (and thus the request object) ?
Answer to the 2 sub-questions:
Is there a reason why the tag decorator does accept the takes_context argument ?
It's because, as you said, tag is run at a lower level, parser-level of the template. There is no context at that point.
How can I access the template context with this decorator (and thus the request object) ?
I don't think you can. Again, because it's a parser-level thing. An interesting example is the block tag. In order to be able to override block tags, it uses the extend tag to pass on some info.
I'm struggling with similar situation. The only thing I can think of is making middleware for process_request that resets some global/singleton context which I access in tags. However this wont help if a template is rendered outside a request, like in a command.
#register.tag takes only two arguments: the name and the compilation function. I think you can try to pass request through the token argument in the compilation function.
UPD:
You can also access it in the Node render method
class TestTagNode(template.Node):
def render(self, context):
return context['request'].user
#register.tag
def test_tag(parser, token):
return TestTagNode()

Setting a variable in middleware to be accessed in the template

I seem to be having difficulty setting a variable in one of my middleware classes that I can then access in the template layer.
The basic layout is this:
class TheMiddleware(object):
def __init__(self, etc):
stuff...
def process_response(self, request, response):
request.my_var = "whatever"
return response
Then on the template for a different view I have:
{% custom_tag arg_a %}
Which is is a template tag that should return the variable from the request:
#register.simple_tag
def custom_tag(arg_a):
return threading.currentThread().request.my_var
This errors out with "Caught AttributeError while rendering: 'WSGIRequest' object has no attribute 'my_var'"
I thought it might be the way I was accessing the request in the template tag. So I added django.core.context_processors.request to my TEMPLATE_CONTEXT_PROCESSORS as in This question and tried passing the request object to the tag, then accessing request directly from the template but with no luck.
I think I lack an understanding on how request objects work. Is it possible to assign a variable to a request object and pick that variable up several views on? I thought the request object was passed through the views, but it seems that instead a new instance is generated.
If that is the case, how would you go about storing a global variable within middleware that you could then access from any point in your app, be it in a view or a template?
Update:
To clear up the confusion (whether mine or others I'm not sure!) I'm not trying to set the request variable in the process_response middleware of a view and then pick it up in the template of that same view. I understand that that wouldn't work because the template has been processed before the variable is saved. (This is a deliberate act on my part).
I have two views, view1 and view2 view one has a decorator that causes the middleware to set the variable in the request. It is the view2 template, which comes after the variable has been set, that I wish to access the variable.
You trying to set variable during processing of response in your middleware.
I think you should be implementing process_request() instead to set the variable.
def process_request(self, request):
request.my_var = "whatever"
return
If you're setting it on the request, I can't see any reason at all to try and use threadlocals here. You should use the context processor as you describe.
The reason for your problem, though, is that process_response is run in the response phase of the request/response cycle: ie, after your view has been called. You should define process_request instead. See here for a description of the order that middleware methods are called.

How come sending a request context gives me access to a setting in my Django template?

In my view, if I specify
def myView(request):
return render_to_response('myTemplate.html', {'user': request.user,},
context_instance=RequestContext(request))
then I can access settings such as STATIC_URL in myTemplate.html.
However, if I specify
def myView(request):
return render_to_response('myTemplate.html', {'user': request.user,})
then I cannot access STATIC_URL. In this latter case, {{ STATIC_URL }} just yields an empty string in the rendered page. In the former case, {{ STATIC_URL }} yields the proper string for the static URL ("/static/").
Why do I need to send a request context to access the STATIC_URL setting in my template?
I am running Django 1.4 on Apache 2.
Read the docs for a better answer. But there is the short answer:
This is because of DRY (DonĀ“t Repeat Yourself), think this: what if you need set the same variable in all the templates through all the views?: context_processors, are methods that add variables to your templates in a more ordered way.
I quote:
Django comes with a special Context class, django.template.RequestContext, that acts slightly differently than the normal django.template.Context. The first difference is that it takes an HttpRequest as its first argument. For example:
c = RequestContext(request, {
'foo': 'bar',
})
The second difference is that it automatically populates the context with a few variables, according to your TEMPLATE_CONTEXT_PROCESSORS setting.
To access the STATIC_URL setting you need to send a request context because by default the RequestContext instance is automatically populated with some variable, accordingly with the TEMPLATE_CONTEXT_PROCESSORS settings which, by default too, reads this:
(...
"django.core.context_processors.static",
...)
About the django.core.context_processors.static context processor, the docs states:
If TEMPLATE_CONTEXT_PROCESSORS contains this processor, every
RequestContext will contain a variable STATIC_URL, providing the value
of the STATIC_URL setting.
If instead, you don't specify the context_instance=RequestContext(request) part. Consider this signature:
render_to_response(template_name[, dictionary][, context_instance][, mimetype])
In this case a basic Context instance is used and (for this reason) only the given dictionary items get injected into the template. This dictionary could or couldn't contain the value of settings.STATIC_URL.
Note: as pointed out in another answer, since Django 1.3 you can directly use the render shortcut instead of render_to_response() with a context_instance argument.
References to official documentation:
render_to_response
Subclassing Context: RequestContext
django.core.context_processors.static
render shortcut
Since you're on 1.4, use the newer render() shortcut. Then you can do:
def myView(request):
return render(request, 'myTemplate.html', {'user': request.user,})

yourlabs-subscription error -- Caught VariableDoesNotExist while rendering

I have been trying to use the updated yourlabs subscription example, and the installation has worked fine except that
Each of the views in the subscription app returns the request variable in the render to template.
this request context variable is not received in the template and as a result I am getting the following error
Caught VariableDoesNotExist while rendering: Failed lookup for key [request] in u
Since this is being returned in every view I can't solve this problem by making some tweaks in a particular template
This is happening because request isn't in your template's context and the template is using some template code that expected it to be there. That code (e.g. a custom template tag) should better handle VariableDoesNotExist
In addition, your views probably shouldn't return request in every response explicitly. Let Django handle this for you.
To do this, add the request template context processor that ships with Django to your TEMPLATE_CONTEXT_PROCESSORS:
TEMPLATE_CONTEXT_PROCESSORS = (
...
'django.core.context_processors.request',
...
)
If you are already using this template context processor, ensure that render_to_response is called with context_instance=RequestContext(request) as the final argument (the below example is from the docs):
def some_view(request):
# ...
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
This ensures that all the dicts returned by the template context processors in TEMPLATE_CONTEXT_PROCESSORS are passed to the template.
You could also use the rendershortcut, which will automatically render the template with an instance of Requestcontext.
Another option added in Django 1.3 is the TemplateResponse, which will also use an instance of RequestContext.