I'd like to work with user data in main base.html which is my main template.
I actually use the login generic view. When I'm logged in on the homepage it gives me user information but in all other pages user is blank.
I've read many things about this: request, RequestContext, I've added django.contrib.auth.context_processors.auth to the processors list.
Any idea how to get this variable to show everywhere?
Two ways:
If you're using django 1.4+, you can use, render() when returning from your views:
def my_view(request):
...
return render(request, 'template.html', ctx)
If you're using older django or you don't like the render approach, you would return RequestContext using render_to_response, like this:
def my_view(request):
...
return render_to_response('template.html', ctx, context_instance=RequestContext(request))
Edit: sorry, forgot to actually answer question. If you're rendering your templates using one of the above ways and have:
django.contrib.auth in your INSTALLED_APPS
auth in midleware
auth in context_processors
(take a look at default settings.py file: https://github.com/django/django/blob/master/django/conf/global_settings.py )
Then you can use: {{ user }} and {{ user.is_anonymous }} to figure out what's going on.
Related
I'm trying to use a Django ListView sub-class to generate a page with a form on it. It's an old school manual HTML form, not a Django-generated one (though I do also have a Django-generated form elsewhere on the same page). Since Django bakes CSRF authentication in, I need to include the CSRF token in that form in order to make it work.
However, I'm not having much luck, even after looking at several related Stack Overflow posts (and fixing things accordingly).
Basically I've got a get method on a ListView subclass, and I've used the method decorator to decorate it with the CSRF decorator:
class FooView(ListView):
#method_decorator(ensure_csrf_cookie)
def get(self, request):
# code for otherwise working view
In my template I have:
<form>
{% csrf_token %}
However, when I view the source of the page after it's been rendered, I just see:
<form>
(no CSRF token).
I'm not explicitly adding the CSRF token to the context because I'm using ListView, and as per https://docs.djangoproject.com/en/1.6/ref/contrib/csrf:
If you are using generic views or contrib apps, you are covered already
I'm sure I'm just missing something basic, but any help explaining what that might be would be greatly appreciated.
You need import this:
from django.template import RequestContext
and then use it like so:
def example():
# Some code
return render_to_response('my_example.html', {
'Example_var':my_var
}, context_instance=RequestContext(request))
This will force a {% csrf_token %} to appear.
I am having problems with user authentication for my django site. I have a log-in screen that seems to work. When the user clicks log-in, I call the django.contrib.auth.login and it seems to work fine. However on subsequent pages have no knowledge that there is a user logged in. Example {% user.is_authenticated %} is false. There are also some menu functions that I want to be available for logged in users such as my-account and logout. Those functions are not available, except on the log-in page. Which is really strange.
This seems to be a user context problem. But I'm not sure how I am supposed to be passing a context around to ensure that my login is stable. Does anyone know at could be going on here? Any advice?
---------part of base.html------------
<!--- The following doesn't register even though I know I'm authenticated -->
{% if user.is_authenticated %}
<div id="menu">
<ul>
<li>My Customers</li>
<li>Customer Actions</li>
<li>My Account</li>
</ul>
</div>
{% endif %}
---------my views.py -----------------
# Should I be doing something to pass the user context here
def customer_list(request):
customer_list = Customer.objects.all().order_by('lastName')[:5]
c = Context({
'customer_list': customer_list,
})
t = loader.get_template(template)
return HttpResponse(t.render(cxt))
If you're using Django 1.3, you can use the render() shortcut, which automatically includes RequestContext for you.
from django.shortcuts import render
def customer_list(request):
customer_list = Customer.objects.all().order_by('lastName')[:5]
return render(request, "path_to/template.html",
{'customer_list': customer_list,})
In this case, you could go one step further, and use the generic ListView:
from django.views.generic import ListView
class CustomerList(Listview):
template_name = 'path_to/template.html'
queryset = Customer.objects.all().order_by('lastName')[:5]
Use a RequestContext.
As Daniel Suggested, use the RequestContext... or better, just use the render_to_response shortcut:
from django.template import RequestContext
from django.shortcuts import render_to_response
def customer_list(request):
customer_list = Customer.objects.all().order_by('lastName')[:5]
return render_to_response(
"path_to/template.html",
{'customer_list':customer_list,},
context_instance=RequestContext(request))
My application uses Django's login view from django.contrib.auth.views.login, with a custom template I made.
I'd like to pass my template an additional argument which will change the login page in a few ways. Actually, I'm trying to show a different login page based on the URL.
How can I pass additional arguments to the login's view & to my custom template?
On Django 1.3 the login view accepts a new extra_context argument in the form of a dictionary.
django/contrib/auth/views.py
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm,
current_app=None, extra_context=None):
To add to Roberto Rosario's answer, you can pass a dictionary of arguments to extra_context inside your urls.py
yourProject/urls.py
from django.conf.urls import url
from django.contrib.auth import views
urlpatterns = [
url(r'^login/$', views.login, {
'template_name': 'your-template-dir/login.html',
'extra_context': {
'additional_arg1': val1,
'additional_arg2': val2,
...
},
}, name="login"),
...
]
Which will then be available in your template.
yourProject/your-template-dir/login.html
{% extends "your-template-dir/base.html" %}
<div>
<p>The value of 'additional_arg1' is {{ additional_arg1 }}.</p>
<p>The value of 'additional_arg2' is {{ additional_arg2 }}.</p>
</div>
Here's Django's official documentation.
The source shows there is only one place that would influence the template context.
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm): # here
So your only option is to hitch a ride on AuthenticationForm or write your own login view (which, by the way, is very simple if you look at the code).
from django.contrib.auth.forms import AuthenticationForm
AuthenticationForm.my_extra_data = 'foobar'
(r'^accounts/login/$', 'django.contrib.auth.views.login', \
{'template_name': 'myapp/login.html', \
'authentication_form': AuthenticationForm }),
Template
{{ form.my_extra_data }}
I was having an heck of time passing extra context variables from my custom login view-function to the template. They were all printing out as the empty string, despite following advice from a number of people a lot smarter than me.
Turns out my urls.py entry was still pointing to the built in login view, not my custom one.
Please don't let this happen to you.
When you eliminate the impossible, whatever remains, however improbable, must be the truth. -- Mr. Spock
{% include 'django.contrib.auth.views.login' %}
I don't want to write everything by hand.. I hate this really, django full of automatic stuff.
Goal is to include registration/login.html into base.html, so that I could have this form in every page
If I include only template itself (registration/login.html), problem appears that "form.login", I mean "form" var is not defined because this one comes from VIEW which called when you going to login url. So how can I call that view MANUALLY with include or at least to grab django.contrib.auth.views.login variables by my self in my own view and pass then to base.html?
P.s. It's not just about login form, I think there will be more situations like this
I have found better solution in #django irc.
They called inclusion tags
I'll give you my code, because I got lot's of problem learning new stuff in django =)
file: templatetags/form_login.py
from django import template
register = template.Library()
from django.contrib.auth.forms import AuthenticationForm
#register.inclusion_tag('registration/login.html')
def form_login():
return { 'form': AuthenticationForm() }
Now you can have your form anywhere, this will prerender template and THAT'S IT! no stupid context processors which requires to modify whole project settings.py, which is really sux if you writing stand alone little application..
If you need login-form on every page
Create a context processor:
def login_form_processor(request):
return {
'login_form': LoginForm(request.POST or None)
}
Add it to settings.CONTEXT_PROCESSORS.
Include the template for login form:
{% with login_form as form %}
{% include "registration/login.html" %}
{% endwith %}
You can also make you form lazy-loading, so form will not be created until it is used for the first time.
from django.utils improt functional
def login_form_processor(request):
create_login_form = lambda: LoginForm(request.POST or None)
return {
'login_form': functional.lazy(create_login_form, LoginForm)
}
But I guess you won't want the lazy-loading feature, because login-form is cheap to initialize.
Reusing views
Concerning the "grabbing variables" part from your question: you cannot grab variable from view. Django view is method which returns response object. You can not get variables from response. However some of views accept extra_context and other attributes. Those attributes allow you to configure those views in urls, or to wrap them with your own view, for example:
def my_login_view(request):
some_extra_data = get_some_data()
extra_context = {
'some_extra_var': some_extra_data
}
return login_view(request, extra_context=extra_context, template="my_template.html")
This is not exactly grabbing the variables from views, more like augmentation of existing views.
If you expect to have more situations like this, do less data-porcessing in views. Call some methods which checks for permissions. Collect some data from context-processors. Return rendered response. Now you can reuse the data in other views.
You can specify the action on the form html to point to the URL that accesses the corresponding view.
If you want a form, say called as login_form always populated in all templates, then put it in the context_processors.
Browsing the code for django.contrib.auth.views, you will see that the variables form, site and *site_name* are passed to the template.
Either you (1) provide your custom registration form or (2) you can just import django.contrib.auth.forms.AuthenticationForm in your view if you want to use it.
I have a page, index.html, that contains both a login and registration form. I have a couple of questions about getting this to work properly
My URLConfig looks like this:
urlpatterns = patterns('djangoproject1.authentication.views',
(r'^$',direct_to_template,{'template':'authentication/index.html'}),
(r'^register/$','register'),
)
1) Using the Django book is a guide, my form looks like this:
<h1>Register</h1>
<form action="/register/" method="post">
{{ form.as_p }}
<input type="submit" value="Register">
</form>
Of course, since the file is index.html, the form doesn't appear when I just go to the page. Do I need a "view" to handle visiting index.html rather than a direct_to_template?
2) My Register code looks like this:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
return HttpResponseRedirect("/register/success/")
else:
form = UserCreationForm()
return render_to_response("authentication/index.html", {'form': form})
This is the django authentication built-in stuff. Do people actually use it? It seems limited. I know I can add more fields to the Django User by using a user profile or something, but what about the UserCreationForm? Should I roll my own form? Should it inherit from UserCreationForm somehow?
direct_to_template by itself can neither produce nor handle forms -- it simply renders a request directly to a template, as its name describes.
You might look into django-registration for registration.
If you're putting two forms on the same page, you'll need a custom view that is capable of rendering and handling both forms, though multi-form pages are notoriously tricky to work with properly. If you have separate forms (and submit buttons), you can add a unique name to each submit input and determine which form (class) to validate and handle based on if name in request.POST.
edit:
After looking more closely at your code, I see that your registration form redirects to a different view; that simplifies things, but you'll still need a custom view for your home page that passes both login and registration forms to the template for rendering.
Alternatively, if you're simply redirecting to pages that handle each form, you can add those forms using direct_to_template's extra_context parameter directly in your urls.py:
from wherever import LoginForm, RegistrationForm
urlpatterns = patterns('djangoproject1.authentication.views',
(r'^$',
direct_to_template,
{
'template': 'authentication/index.html',
'extra_context': {
'reg_form': RegistrationForm(),
'login_form': LoginForm()
}
}
),
(r'^register/$', 'register'),
)
This approach isn't the cleanest, but it's an option if you really wanted to use generic views.
It sounds like you'll probably want to use a different generic view instead of direct_to_tepmlate. Take a look at the create object generic view. I usually just create a view, typically I end up needing to do more than what a generic view will allow me to do easily.