I have a login-page set as my homepage, localhost/mysite. I can login and successfully be redirected to localhost/mysite/mainpage.
The issue is that I can bypass the login simply by just entering the path in the URL, for example; I navigate to the homepage where the login-form is, then I just add /mainpage to localhost/mysite/ which successfully loads localhost/mysite/mainpage.
As you could imagine, this is not great. Does anyone know what I did wrong here?
My view
def index(request):
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
messages.info(request, "OK")
return redirect('/mysite/mainpage')
else:
messages.error(request, "NOT OK")
form = AuthenticationForm()
return render(request, 'mysite/login.html', {"form":form})
My urls.py
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^mainpage/$', views.main),
]
You can use the #login_required decorator [Django-doc] on your main view. This will redirect to the path set by the LOGIN_URL setting [Django-doc] to log in the user:
# app/views.py
from django.contrib.auth.decorators import login_required
def index(request):
# …
#login_required
def main(request):
# …
and in the settings.py:
# settings.py
# …
LOGIN_URL = 'index'
# …
EDIT: You can omit the ?next= query parameter, by setting the redirect_field_name=… parameter to None:
#login_required(redirect_field_name=None)
def main(request):
# …
Related
I am attaching my code in views and urls.py. Whenever the server runs, I want to see the login page first, but I am seeing an error that this page is not working.
#views.py
def loginPage(request):
if request.user.is_authenticated:
return redirect('/')
else:
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('/')
else:
messages.info(request, 'Username OR password is incorrect')
context = {}
return render(request, 'accounts/login.html', context)
# urls.py
urlpatterns = [
path('', views.loginPage, name="login"),
path('index/',views.index,name="index"),
You should pass #login_required decorator in your view. If you don't want to pass this decorator in your every view there are second way which you can do using middleware. In middleware you check the user is authenticated or not. If yes it redirects user to index page other way to login page. Here is an example:
Create middleware.py file and write this code inside it:
from django.utils.deprecation import MiddlewareMixin
from django.urls import reverse
from django.shortcuts import redirect
class LoginCheckMiddleWare(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
modulename = view_func.__module__
user = request.user # Who is the current user ?
if user.is_authenticated:
return redirect(reverse('index-page'))
else:
if request.path == reverse('login_page') or modulename == 'django.contrib.auth.views':
pass
else:
return redirect(reverse('login_page'))
After that add this line inside MIDDLEWARE in settings.py file:
'folder.middleware.LoginCheckMiddleWare', instead of folder write your middleware file located folder
When trying to access a private page, this view redirects to the login page if the user is not authenticated, and after the authentication was done, I wanted it to redirect to the private page instead of success_url, with LoginView configured for a FormView. When I access the private page without logging in, this standard url is generated according to django
http://localhost/myapp/login/?next=/myapp/private-page/,
in this case the url that will be redirected after login should be myapp/private-page instead of success_url
My code looks like this:
# myapp/urls
from django.urls import path
from . import views
app_name = 'myapp'
urlpatterns = [
path("", views.home, name='home'),
path("login/", views.LoginRequest.as_view(), name='login'),
path('logout/', views.logout_request, name='logout'),
path("signup/", views.signup, name='signup'),
path("private-page/", views.PrivatePage.as_view()),
]
# myapp/views.py
class PrivatePage(LoginRequiredMixin, TemplateView):
template_name = 'myapp/private-page.html'
login_url = 'myapp:login'
class LoginRequest(FormView):
template_name = 'myapp/auth/login/login.html'
form_class = LoginForm
success_url = 'myapp:home'
def form_valid(self, form):
"""If the form is valid, redirect to the supplied URL."""
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(self.request, user)
messages.info(self.request, f'You are connected as {username}')
# here the code to redirect to the private-page
# instead this return
return redirect(self.get_success_url())
else:
self.form_invalid(form)
def form_invalid(self, form):
"""If the form is invalid, render the invalid form."""
for key in form.errors:
messages.error(self.request, form.errors[key])
return self.render_to_response(self.get_context_data(form=form))
I am building an app that allows users to view posts. However, every time I try to log in if I do not set the LoginRequiredMixin the user will still be able to view posts after logging out. But when I set the LoginRequiredMixin everytime user puts info it keeps going back to main page and nothing happens.
my home/views.py
#login_required
def home(request):
posts = Post.objects.all()
context = {'posts':posts}
return render(request, 'home/home.html', context)
class PostListView(ListView):
model = Post
template_name = 'home/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['-date_posted']
my home/urls.py:
path('',views.PostListView.as_view(), name='home'),
my main/urls.py
urlpatterns=[
path('signup/',views.signup,name='signup'),
path('signin/',views.user_login, name='user_login'),
path('signout/', views.user_logout, name='user_logout'),
path('',views.main_page,name='main_page'),
path('edit/', views.edit_profile, name='edit_profile'),
path('', include('django.contrib.auth.urls')),
]
my main/views.py:
def main_page(request):
return render(request,'main/user_login.html')
#login_required
def user_logout(request):
logout(request)
return redirect('main:main_page')
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
return redirect('main:main_page')
else:
form = SignUpForm()
return render(request, 'main/signup.html', {'form': form})
def user_login(request):
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = authenticate(request, username=username, password=password)
if user is not None:
return redirect(reverse('home:home'))
else:
messages.error(request,'Sorry, the username or password you entered is not valid please try again.')
return HttpResponseRedirect('/')
else:
form=AuthenticationForm()
return render(request, 'main/user_login.html', {"form":form})
int my settings.py I only have:
LOGIN_URL = 'main:main_page'
I have been working a lot on this and I cannot find how to fix this issue.
Thanks in advance!
I guess the authentication is failing. However here is some snippet you can try.
from django.shortcuts import render,redirect
from django.contrib.auth import login,logout
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.decorators import login_required
def loginView(request):
if request.method == 'POST':
# Authentication form is provided by django, it will parse username and password
# in the post request
form = AuthenticationForm(data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
return redirect('home:home')
else:
form = AuthenticationForm()
return render(request, 'main/user_login.html', context={'form': form})
#login_required
def logout_request(request):
logout(request)
return redirect('home:user_login')
In settings.py make sure you have following properties set:
LOGIN_URL = reverse_lazy('home:user_login')
LOGIN_REDIRECT_URL = reverse_lazy('home:home')
LOGOUT_REDIRECT_URL = reverse_lazy('home:user_login')
Note: If you are using custom made user(other than default user model provided by djnago) then make sure you have following property in settings.py set, otherwise AuthenticationForm won't work.
AUTH_USER_MODEL = 'AppName.YourCustomUserModel'
The login function is not working , after i call login , authenticated is set 'true' but after i redirect to 'main' view authenticated is set 'false'. How to keep the user logged in even after redirection?
class LoginForm(forms.Form):
user = forms.CharField()
password = forms.CharField()
def login(self):
try:
cred = users.objects.get(username = user)
if password==cred.password):
return (True, cred)
return (False, 'Invalid Password.')
except:
return (False, 'Not exist')
from django.contrib.auth import login as auth_login
def login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
valid, message = form.login()
if valid:
auth_login(request, message)
print(request.user.is_authenticated)
# this is not working
return redirect(main)
else:
return redirect(login)
form = LoginForm()
args = {'form': form}
return render(request, 'accounts/login.html', args)
def main(request):
print(request.user.is_authenticated)
You shouldn't write check your user credentials in form class. Do it in your login view. Example:
# views.py
from django.contrib.auth import authenticate, login
from django.urls import reverse
from django.shortcuts import redirect, render
def login_view(request): #changed_the name shouldn't be login
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data["username"]
password = form.cleaned_data["password"]
user = authenticate(username, password)
if user:
login(user)
return redirect(reverse("main"))
else:
return redirect(reverse("login"))
form = LoginForm()
args = {"form": form}
return render(request, 'accounts/login.html', args)
# urls.py
urlpatterns = [
path("login/", views.login_view, name="login"), # <-- really important
path("main/", views.main_view, name="main")
]
To summarize - to redirect to another page use redirect function. If you set name parameter in url of you view, you can reffer to this view using reverse. Also don't reinvent the wheel and write your own authentication function. Django provides: authenticate(username, password) and login(user) function.
I'm trying to make a limited user edit page if the login is not executed.
After logging in, the edit page opens with any user_id in the url.
Although edit page should be open only with user_id already logged in user.
For example, I logged in with user_id=7, so only one next url (http://127.0.0.1:8000/user/7/edit) have to have access to edit page.
And this edit page is available by any next urls also (http://127.0.0.1:8000/user//edit)
Are there any errors or mistakes in my code?
I already have cleared cache in Opera and Chrome, but issue still exist.
Django ver. 1.11.9.
LOGIN_URL is not defined in settings.py
urls.py
urlpatterns = [
url(r'^login/$', user_login, name='user-login',),
url(r'^(?P<user_id>\d+)/edit$', user_edit, name='user-edit',),
]
views.py
def user_login(request):
login_form = AuthenticationForm(request.POST or None)
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user:
login(request, user)
print("next is {}".format(request.GET.get('next')))
return redirect(user_edit, user.id)
else:
return redirect(user_login)
return render(request, 'user_login.html', {'form': login_form})
#login_required(login_url='/user/login/')
def user_edit(request, user_id):
print(request, request.user)
print("next is {}".format(request.GET.get('next')))
return render(request, 'user_edit.html', {'userid': user_id, 'user': request.user})
The login_required decorator only checks that the user is logged in. If you want to check that the logged-in user has access to an object, then you need to do that in the view. For example:
from django.http import Http404
#login_required(login_url='/user/login/')
def user_edit(request, user_id):
print(request, request.user)
if request.user.id != user_id:
raise Http404
return render(request, 'user_edit.html', {'userid': user_id, 'user': request.user})