Let's continue to improve the voting application . In the last chapter , After the user logs in successfully, we pass session Retained user information , Then we can make some adjustments , It is required to log in before voting for teachers , Logged in users can vote , Otherwise, guide the user to the login page , To do this, we can modify the view function in this way .
def praise_or_criticize(request: HttpRequest):
""" vote """
if 'username' in request.session:
try:
tno = int(request.GET.get('tno', '0'))
teacher = Teacher.objects.get(no=tno)
if request.path.startswith('/praise'):
teacher.good_count += 1
else:
teacher.bad_count += 1
teacher.save()
data = {
'code': 200, 'message': ' Successful operation '}
except (ValueError, Teacher.DoesNotExist):
data = {
'code': 404, 'message': ' operation failed '}
else:
data = {
'code': 401, 'message': ' Please log in first '}
return JsonResponse(data)
The front page receives {'code': 401, 'message': ' Please log in first '}
after , You can direct the user to the login page , The modified teacher.html Page JavaScript The code department is shown below .
<script> $(() => {
$('.comment > a').on('click', (evt) => {
evt.preventDefault() let a = $(evt.target) $.getJSON(a.attr('href'), (json) => {
if (json.code == 200) {
let span = a.next() span.text(parseInt(span.text()) + 1) } else if (json.code == 401) {
location.href = '/login/?backurl=' + location.href } else {
alert(json.message) } }) }) }) </script>
Be careful : In order to return to the voting page after the login is successful , We set up a... When logging in
backurl
Parameters , Put... In the current browser URL As the returned page address .
In this way, we have implemented the restriction that users must log in to vote , But here comes a new problem . If there are many functions in our application that require users to log in first , For example, export the previous Excel The functions of reporting and viewing statistical charts are restricted , So do we need to add code to each view function to check session Is the login user information included in the ? The answer is No , If this is done , Our view functions are bound to be filled with a lot of duplicate code . Master programmer Martin Fowler Once said : Code has a lot of bad taste , Repetition is the worst . stay Django In the project , We can put the repetitive code of verifying whether the user logs in into the middleware .
The middleware is installed in Web Apply the components between the request and response processes , It's all over the place Web The application acts as an interception filter , Request and response can be intercepted through Middleware , And filter requests and responses ( Simply put, it is to perform additional processing ). Usually , A middleware component focuses only on accomplishing a specific task , for example :Django The framework passes SessionMiddleware
The middleware implements session Support for , And through the AuthenticationMiddleware
The middleware is based on session Request authentication for . By combining multiple middleware , We can accomplish more complex tasks ,Django That's what the framework does .
Django The configuration file of the project contains the configuration of the middleware , The code is as follows .
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Let's explain the functions of these middleware :
/
In the course of the request , The above middleware will be executed from top to bottom in the written order , And then there was URL analysis , Finally, the request will come to the view function ; In the process of response , The above middleware will be executed from bottom to top in the written order , It is the reverse order of middleware execution at the time of request .
Django There are two ways to implement the middleware in : Class based implementation and function based implementation , The latter is more similar to the writing of ornaments . Decorators are actually applications of the proxy pattern , Will crosscut the focus function ( Functions that are not necessarily related to normal business logic , for example : Identity Authentication 、 logging 、 Functions such as code conversion ) Put in proxy , The delegate object completes the behavior of the delegate object and adds additional functions . Middleware intercepts and filters user requests and responses and adds additional processing , At this point, it is completely consistent with the decorator , So the writing method of middleware based on function is almost the same as that of decorator . Now we use the customized middleware to realize the function of user login authentication .
""" middlewares.py """
from django.http import JsonResponse
from django.shortcuts import redirect
# The resource path that needs to be logged in to access
LOGIN_REQUIRED_URLS = {
'/praise/', '/criticize/', '/excel/', '/teachers_data/',
}
def check_login_middleware(get_resp):
def wrapper(request, *args, **kwargs):
# The requested resource path is in the above collection
if request.path in LOGIN_REQUIRED_URLS:
# The conversation contains userid It is deemed to have logged in
if 'userid' not in request.session:
# Judgment is not Ajax request
if request.is_ajax():
# Ajax Request returns JSON The data prompts the user to log in
return JsonResponse({
'code': 10003, 'hint': ' Please log in first '})
else:
backurl = request.get_full_path()
# Not Ajax Request direct redirection to the login page
return redirect(f'/login/?backurl={
backurl}')
return get_resp(request, *args, **kwargs)
return wrapper
Modify the configuration file , Activate the middleware to make it effective .
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware',
'vote.middlewares.check_login_middleware',
]
Note the order of the elements in the middleware list above , When a request is received from a user , The middleware is executed from top to bottom , After this line of middleware , The request will eventually reach the view function . Of course , In the process , User requests can be intercepted , Just like the middleware we customized above , If a user accesses a protected resource without logging in , The middleware will redirect the request directly to the login page , The following middleware and view functions will no longer be executed . In response to user requests , The above middleware will be executed from bottom to top , In this way, we can further process the response .
The order in which middleware is executed is very important , For dependent middleware, it must be ensured that the dependent middleware is placed in front of the dependent middleware , For example, the middleware we just customized should be put into SessionMiddleware
Behind , Because we rely on this middleware to bind requests session
Object to determine whether the user is logged in .
thus , In addition to the function of restricting the number of users' votes , The voting application is basically completed , For the complete code of the whole project, please refer to https://github.com/jackfrued/django1902, Among them, the mobile phone verification code function used by users during registration, please use your own registered SMS platform to replace it . If you need to vote, apply the complete video explanation , You can scan the code on the home page and leave a message to contact the author to get the video download address , Thank you for your understanding and support .