Reputation: 990
I'm trying to $.load()
a Django template that uses {% if user.is_authenticated %}
. Unfortunately, the user
object is undefined in the template when rendered on the server only if it's in response to an AJAX-generated HTTP request.
my_template.html:
{% if user.is_authenticated %}
<div>This should be printed</div>
{% else %}
<div>But this is because there is no user object</div>
{% endif %}
my_loader.html:
{% if user.is_authenticated %}
<div>This works fine because I'm logged in</div>
{% endif %}
<div id="template'></div>
<script>
$('#template').load('/my_template.html');
</script>
views.py (using django-annoying's @render_to
decorator):
@render_to('my_template.html')
def my_template(request):
return {}
The problem, as I understand it, is that the "context" available in the rendering of my_loader.html is not made available to the server through .load()
. I don't know whether this "context" is a session, a cookie, or something in the header, but the result is that when the server renders my_template.html from an HTTP request generated through AJAX, there is no user
object. When I load it organically in the browser it works fine.
If it helps:
xhrFields: { withCredentials: true }
headers: { 'sessionid': $.cookie('sessionid') }
. The sessionid cookie did not exist (although csrftoken did, so I know I was looking in the right place).Any idea how to make the user
object from my_loader.html available to the server when it loads pages like my_template.html via AJAX?
Upvotes: 1
Views: 1527
Reputation: 990
So I feel bad because there's actually nothing wrong with my example code--in my attempts to distill the complex actual code down to an abstract level to present it to you all, I inadvertently left out a complexity that was the root cause of my problem.
Turns out WTK's and my original intuition that the cookie would be passed in the .load()
request by default was, in fact, correct (inspecting the HTTP requests confirms).
So the real issue is that actually, I didn't have one template but two nested, and the latter one was actually a template tag. So the real structure was more like:
my_template.html:
Some stuff
{% my_template_tag %}
my_template_tag.html:
{% if user.is_authenticated %}
<div>This should be printed</div>
{% else %}
<div>But this is because there is no user object</div>
{% endif %}
tags.py
@register.inclusion_tag('my_template_tag.html')
def my_template_tag():
return {}
... where views.py and my_loader.html are the same as presented above. In retrospect, I should've noticed that the my_template_tag()
did not take a request
param, which means that it wouldn't be in the RequestContext to make user
available. Basically: template tags don't implicitly have the request
in their contexts as templates do, and since the user
just comes from request.user
it is also not available.
For those who may later read this, there are two solutions:
user
object manually in as a parameter to the template_tag.{% include %}
with the with
keyword, if possible, as it passes the request by default.Thanks, still, for all your help rubber-ducking this! I couldn't have figured out the real problem without you guys forcing me to go back and question my original assumptions!
Upvotes: 0
Reputation: 16971
I assume you expected {% if user.is_authenticated %}
to be evaluated on Javascript side? Well, it's not how this works. Javascript has no idea of what's on the server side, and how to parse, evaluate or bind the user template variable.
In order for $('#template').load('/my_template.html');
to work, you have to make sure that my_template.html
gets rendered by Django before it's returned.
Just create a view (in Django) to render my_template.html
. Don't worry about the session - it should work because along with your ajax request, cookies (which identify session) are sent as well, so Django can pick the right session, and pull user object from it.
Upvotes: 1