I am trying to write a test for logging out a user in Django. Here is the code:
urls.py
from django.conf.urls import url
from django.contrib import admin
from accounts.views import LoginView, LogoutView
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', LoginView.as_view(), name='login'),
url(r'^logout/', LogoutView.as_view(), name='logout'),
]
views.py
from django.http import HttpResponseRedirect
from django.contrib.auth import login, logout
from django.views.generic import View
class LogoutView(View):
def get(self, request):
logout(request)
return HttpResponseRedirect('/')
tests.py
from django.test import TestCase, Client
from django.contrib.auth.models import User
class LogoutTest(TestCase):
def setUp(self):
self.client = Client()
self.user = User.objects.create_user(
username='user1',
email='user1_123#gmail.com',
password='top_secret123'
)
def test_user_logs_out(self):
self.client.login(email=self.user.email, password=self.user.password)
self.assertTrue(self.user.is_authenticated)
response = self.client.get('/logout/')
self.assertFalse(self.user.is_authenticated)
self.assertRedirects(response, '/', 302)
The assertion self.assertFalse(self.user.is_authenticated) is failing. Testing through the browser seems to work fine. It seems like the user would not be authenticated after calling logout(). Am I missing something?
It seems like the user would not be authenticated after calling logout(). Am I missing something?
.is_authenticated [Django-doc] does not check if a user is logged in. Every real User returns always True for is_authenticated. An AnonymousUser [Django-doc] will return False for example. If you thus log out, then request.user will be the AnonymousUser, and thus not be authenticated.
In other words, if you use request.user.is_authenticated, you will call this on the logged-in user if the session is bounded to a user (you logged in with the browser), and you call this on the AnonymousUser in case the browser did not log in a user/the browser logged out.
Related
I am a new Django user and I just created a registration and login system for my website in Django 1.11. I am struck when I go to login section of my website. I get the error as mentioned "login() missing 1 required positional argument: 'user'" and I can't figure out what's wrong with the login function and the variable 'user'. Kindly help me. Thanks in advance. Here is my code:
urls.py:
from django.conf.urls import url
from . import views
from django.contrib.auth import login
app_name='one'
urlpatterns = [
url(r'^games$',views.games,name='games'),
url(r'^others$',views.others,name='others'),
url(r'^about$',views.about,name='about'),
url(r'^upload$',views.UploadFile.as_view(),name='upload'),
url(r'^register$',views.UserFormView.as_view(),name='register'),
url(r'^login/$', login, name='login'),
]
views.py:
from django.shortcuts import render,redirect
from django.contrib.auth import authenticate, login
from django.views.generic.edit import CreateView
from .models import file
from django.views.generic import View
from .forms import user_form
class UserFormView(View):
form_class = user_form
template_name = 'one/register_form.html'
def get (self,request):
form = self.form_class(None)
return render(request,self.template_name,{'form':form})
def post (self,request):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit = False)
username= form.cleaned_data['username']
password= form.cleaned_data['password']
user.set_password(password)
user.save()
user= authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
redirect('one:profile')
return render(request,self.template_name,{'form':form})
You’ve got the import wrong. You need to import the login view:
from django.contrib.auth.views import login
At the moment you have imported the login function that actually logs the user in.
The login view you are using is deprecated in Django 1.11. You can switch to the new class-based LoginView:
from django.contrib.auth.views import LoginView
url(r'^login/$', LoginView.as_view(), name='login'),
Well, this question has been asked by many users, and I have tried some of the resolution provided in the query, but that doesn't seem to resolve my issue, maybe I am doing some other mistake.
I am trying to create a simple user registration/login/logout forms
SchoolnSkill ---Project name, and below is the SchoolnSkill/url details:-
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^user_info/', include('user_info.urls')),
]
user_info--App name, and the user_info/url details are below:-
from django.conf.urls import url
from . import views
urlpatterns = [
# url(r'^$', views.index, name='index'),
url(r'^registration/', views.UserFormView, name='registration')
]
My views.py output is as below:-
from django.shortcuts import render, redirect
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse_lazy
from django.contrib.auth import authenticate, login
from django.views import generic
from .models import Registration
from django.views import View
from .forms import UserForm
class UserFormView(View):
#from_class = UserForm
template_name = 'user_info/registration_form.html'
#dispaly blank form, new user coming to the website
def get(self, request):
form = self.UserForm(None)
return render(request, self.template_name, {'form':form})
def post(self, request):
form = self.UserForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
user.save()
form.py content as below:
from django.contrib.auth.models import User
from django import forms
from django.forms import ModelForm
class UserForm(forms.ModelForm):
password = forms.CharField(widget =forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'email', 'password']
I am using below versions:
Python 3.6
Django 1.11.3
Spyder IDE
I am pretty sure that am doing something silly.
Please help.
below is the error message:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/user_info/
Using the URLconf defined in SchoolnSkill.urls, Django tried these URL patterns, in this order:
^admin/
^user_info/ ^registration/ [name='registration']
The current path, user_info/, didn't match any of these.
as you are using class based view you need to add as_view in the url
so
change this in user_info url to
urlpatterns = [
url(r'^registration/', views.UserFormView.as_view(), name='registration')
]
I am trying to redirect a user who just logged in to his/her's respective account page.
This question has been asked a few times, but most of them are old and use static urls like /accounts/profile/: Django - after login, redirect user to his custom page --> mysite.com/username. I would like to use dynamic url naming to achieve this solution.
For example, what if my account landing page has the following url pattern?
url(r'^account/(?P<pk>\d+)/(?P<name>\w+)/$', AccountLanding.as_view(), name="account-landing" )`.
How would I pass the args in settings.py for LOGIN_REDIRECT_URL?
It isn't possible to use dynamic arguments (e.g. the primary key of the logged in user) in the LOGIN_REDIRECT_URL in your settings.py.
In Django 1.11+, you can subclass LoginView, and override get_success_url so that it dynamically redirects.
from django.contrib.auth.views import LoginView
class MyLoginView():
def get_success_url(self):
url = self.get_redirect_url()
return url or reverse('account_landing', kwargs={'pk': self.request.user.pk, 'name': self.request.user.username})
Note the url = self.get_redirect_url() line is required to handle redirects back to the previous page using the querystring, e.g. ?next=/foo/bar
Then use your custom login view in your URL config.
url(r'^login/$', MyLoginView.as_view(), name='login'),
For earlier versions of Django, it isn't possible to customise the function-based login view in the same way.
One work around is to create a view that redirects to your landing page:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
#login_required
def account_redirect(request):
return redirect('account-landing', pk=request.user.pk, name=request.user.username)
Create a url pattern for this view:
urlpatterns = [
url(r'^account/$', account_redirect, name='account-redirect'),
]
Then use that view as LOGIN_REDIRECT_URL:
LOGIN_REDIRECT_URL = 'account-redirect'
On Django 4.x there is a new attribute called next_page
and you can use it as:
from django.contrib.auth.views import LoginView
from django.urls import reverse_lazy
class MyLoginView():
...
next_page = reverse_lazy('profile', kwargs={'id': pk},
name='username'))
...
I'm using django's auth module to handle the user login, logout and registration in my website.
The problem is that when I register a new user, I new to redirect to another url, and then, since the model is created but doesn't automatically log in, I need to navigate to /login/ and log in manually.
I would like my site to do this automatically. By that I mean that:
You click on the register button in home.html. You fill in the form and submit it.
The website AUTOMATICALLY creates the new user model, logs you in and redirects you to home.html with the user logged in.
Urls.py looks like this:
from django.conf.urls import include, url, patterns
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from django.contrib.auth import views as auth_views
from django.contrib.auth.forms import UserCreationForm
from browse.views import UserCreate
urlpatterns = patterns('',
url(r'',include('browse.urls')),
url(r'^$', 'browse.views.home_page', name='home'),
url(r'^admin/', include(admin.site.urls)),
url(r'^login/$', auth_views.login, {'template_name': 'browse/login.html'}),
url(r'^register/$', UserCreate.as_view(
template_name='browse/register.html',
form_class=UserCreationForm,
success_url='/register/'
)),
url(r'^logout/$', 'browse.views.logout_view', name='logout'),
url(r'^', include('django.contrib.auth.urls')),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
and views.py looks like this:
from django.shortcuts import render, redirect
from django.views.generic.edit import CreateView
from browse.models import Pattern
from django.contrib.auth.models import User
from django.contrib.auth import logout, login
class PatternCreate(CreateView):
model = Pattern
fields = ['name','description','license', 'xcheme', 'pictures', 'video']
class UserCreate(CreateView):
model = User
def post(self, request):
return login(request, User.objects.get(username=request.POST['username']))
def home_page(request):
return render(request, 'browse/home.html')
def pattern_detail(request, pk):
pattern = Pattern.objects.get(pk=pk)
return render(request, 'browse/pattern_detail.html', {'pattern': pattern})
def logout_view(request):
logout(request)
return redirect('/')
As you can see, when you GET /register/ the register form is rendered. When I POST to /register/, I want to execute the view as normally AND then add:
def post(self, request):
return login(request, User.objects.get(username=request.POST['username']))
But It looks like I'm overriding the default view instead of adding to it, because the model doesn't get saved, since I get this error:
Exception Value:
User matching query does not exist.
How can I fix it?
Thank you so much beforehand.
Okay, it was a really dumb question. Luckily, I could figure it out:
def post(self, request):
super(UserCreate, self).post(request)
login_username = request.POST['username']
login_password = request.POST['password1']
created_user = authenticate(username=login_username, password=login_password)
login(request, created_user)
return redirect('/')
All I had to do is call super() and the parent function is executed. Then, my code executes.
I am quite new in django.I would like to authenticate a user. But I am unable to do it using authenticate function. I have looked over authenticate function in django. and there it's always showing TypeError. I have used both unicode and string in separate time but always it's showing the TypeError.
Please any help will be appreciated.
I am attching my code below:
def loginTest(request):
if request.method == 'POST':
user = authenticate(username=request.POST['username'], password=request.POST['password'])
if user is not None:
login(request,user)
return HomePage(request)
else:
return HttpResponseRedirect('/login/')
def login(request):
return render_to_response('login.html', {}, context_instance=RequestContext(request))
#login_required(login_url='/login/')
def HomePage(req):
templ = get_template('HomePage.html')
variables = Context({})
output = templ.render(variables)
return HttpResponse(output)
First off, you're defining a "login" view yourself, so when you try to call login(request, user) (what I assume is Django's built in "login" function which sets the user session), it is instead calling your function:
def login(request):
return render_to_response('login.html',{},context_instance=RequestContext(request))
Second, where did the TypeError occur? I assume since you know the nature of the error you've gotten to the Django traceback error page, if you could post the "copy-and-paste view" of the traceback itself, that would be enormously helpful.
You're also doing some funky things with your views that can be easily cleaned up by some shortcut functions. :)
However, since the nature of your question is how to do authentication in Django, here is the base you need to implement a manual login process, mostly just taken from the relevant documentation:
views.py
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
def loginTest(request):
username = request.POST["username"]
password = request.POST["password"]
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
HttpResponseRedirect("/")
else:
HttpResponseRedirect("/login/")
#login_required(login_url="/login/")
def HomePage(request):
return render(request, "HomePage.html")
urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'authtest.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^login/', 'django.contrib.auth.views.login'),
url(r'^', 'custom.views.HomePage'),
)
Also, for future reference, it would be helpful for you to post your entire script so we can see what you have imported at the top.