Using the 'next' Parameter on the Login Page
Determine if a next parameter exists in the URL of the user's login page. If it does, redirect to the URL the user was trying to access before logging in.
A common practice is to modify the login logic in the LoginView handler by adding the following code:
# Check if the request URL contains a 'next' parameter
next = request.GET.get("next")
# If it exists, redirect to the URL specified by 'next'
if next:
return redirect(next)
else:
# If not, redirect to the home page
return redirect(reverse("goods:index"))
Cmoplete example of a login view:
class LoginView(View):
"""Login"""
def get(self, request):
"""Provide login page"""
return render(request, "login.html")
def post(self, request):
"""Handle login data"""
# Get parameters
user_name = request.POST.get("username")
password = request.POST.get("pwd")
remembered = request.POST.get("remembered") # Remember username option
# Validate parameters
if not all([user_name, password]):
# Incomplete parameters
return render(request, "login.html")
# Authenticate user using Django's authentication system
user = authenticate(username=user_name, password=password)
if user is None:
# Invalid login credentials
return render(request, "login.html", {"errmsg": "Incorrect username or password!"})
# Check if user is active
if user.is_active is False:
return render(request, "login.html", {"errmsg": "User not activated!"})
# Save user login state using Django's login function
login(request, user)
# Set session expiry based on 'remember me' option
if remembered != "on":
# User did not check the box
request.session.set_expiry(0) # Temporary session
else:
# User checked the box
request.session.set_expiry(None) # Use Django's default expiration
# After successful login
# Check for 'next' parameter in the URL
next = request.GET.get("next")
# If present, redirect to that URL
if next:
return redirect(next)
else:
# Otherwise, redirect to home page
return redirect(reverse("goods:index"))
When accessing a page that requires authentication (e.g., the user center), the URL can be modified to include the original page. For example:
- Original URL before login:
http://127.0.0.1:8000/users/login?next=/cart/ - After login, the user is redirected back to
/cart/.
How to Log Out a User
To log out a user who has logged in via django.contrib.auth.login(), use django.contrib.auth.logout() in your view. It takes an HttpRequest object and returns nothing.
Define a logout view:
from django.contrib.auth import authenticate, login, logout
class LogoutView(View):
"""Logout"""
def get(self, request):
# Use Django's logout function to clear session data
logout(request)
# Redirect to home page
return redirect(reverse("goods:index"))
Define the URL pattern:
url(r'^logout$', views.LogoutView.as_view(), name="logout"),
After logging in, session information is stored. By visiting the logout URL (e.g., http://127.0.0.1:8000/users/logout), the session is cleared and the user is redirected to the specified page.
Restricting Access to Logged-In Users Only
Using the login_required decorator:
login_required([redirect_field_name=REDIRECT_FIELD_NAME, login_url=None])
As a shortcut, you can use the login_required() decorator:
from django.contrib.auth.decorators import login_required
@login_required(redirect_field_name='my_redirect_field')
def my_view(request):
...
The login_required() decorator does the following:
- If the user is not logged in, redirect to
settings.LOGIN_URLand pass the current absolute path in the query string (e.g.,/accounts/login/?next=/polls/3/). - If the user is logged in, execute the view normally. The view code can safely assume the user is authenticated.
By default, the redirect path after successful authentication is stored in a parameter called "next" in the query string. You can use a different name by passing the redirect_field_name parameter to login_required().
For class-based views, you can create a mixin class:
from django.contrib.auth.decorators import login_required
class LoginRequiredMixin(object):
"""Mixin to require user login"""
@classmethod
def as_view(cls, **initkwargs):
view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
return login_required(view)
Then use it in your view:
from utils.views import LoginRequiredMixin
class AddressView(LoginRequiredMixin, View):
"""User address"""
def get(self, request):
# Provide user address page
user = request.user
try:
address = user.address_set.latest("create_time")
except Address.DoesNotExist:
address = None
context = {
"address": address
}
return render(request, "user_center_site.html", context)
def post(self, request):
"""Update address information"""
user = request.user
recv_name = request.POST.get("recv_name")
addr = request.POST.get("addr")
zip_code = request.POST.get("zip_code")
recv_mobile = request.POST.get("recv_mobile")
if all([recv_name, addr, zip_code, recv_mobile]):
Address.objects.create(
user=user,
receiver_name=recv_name,
detail_addr=addr,
zip_code=zip_code,
receiver_mobile=recv_mobile
)
return redirect(reverse("users:address"))
Add a URL pattern for the address view:
url(r'^address$', views.AddressView.as_view(), name="address"),
In your settings file, specify the login URL for unauthenticated users:
LOGIN_URL = '/users/login'
When an unauthenticated user tries to access a protected URL (e.g., /users/address), they will be redirected to the login page.