登录

在使用authenticate进行验证后,如果验证通过了。那么会返回一个user对象,拿到user对象后,可以使用django.contrib.auth.login进行登录。

这里使用的models是继承自AbstractBaseUser的模型

  1. # models.py
  2. from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
  3. from django.contrib.auth.models import PermissionsMixin
  4. class UserManager(BaseUserManager):
  5. def _create_user(self, phone, username, password, **kwargs):
  6. # 这是一个受保护函数,只能被类自己中调用
  7. # 作为create_user和create_superuser的被调用函数
  8. if not phone:
  9. raise ValueError("必须传递手机号码")
  10. if not password:
  11. raise ValueError("必须传递密码")
  12. user = self.model(phone=phone, username=username, **kwargs) # self.model表示当前模型
  13. user.set_password(password) # password只能这样设置
  14. user.save()
  15. return user
  16. def create_user(self, phone, username, password, **kwargs):
  17. kwargs["is_superuser"] = False # 添加is_superuser键值对
  18. return self._create_user(phone=phone, username=username, password=password, **kwargs)
  19. def create_superuser(self, phone, username, password, **kwargs):
  20. kwargs["is_superuser"] = True
  21. return self._create_user(phone=phone, username=username, password=password, **kwargs)
  22. class InheritTwo(AbstractBaseUser, PermissionsMixin):
  23. phone = models.CharField(max_length=11, unique=True)
  24. username = models.CharField(max_length=20)
  25. password = models.CharField(max_length=20)
  26. address = models.CharField(max_length=100)
  27. is_active = models.BooleanField(default=True)
  28. USERNAME_FIELD = 'phone'
  29. REQUIRED_FIELDS = []
  30. objects = UserManager()
  31. def get_full_name(self):
  32. return self.username
  33. def get_short_name(self):
  34. return self.username

配置settings.py中的AUTH_USER_MODEL='appname.InheritTwo',且为第一次数据库迁移

html编写

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Login</title>
  6. </head>
  7. <body>
  8. <form action="" method="post">
  9. <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
  10. <table>
  11. <tbody>
  12. <tr>
  13. <td>登陆手机号:</td>
  14. <td><input type="text" name="phone"></td>
  15. </tr>
  16. <tr>
  17. <td>密码:</td>
  18. <td><input type="password" name="password"></td>
  19. </tr>
  20. <tr>
  21. <td>
  22. <label for="">
  23. <input type="checkbox" name="remember" value="1"> 记住我
  24. </label>
  25. </td>
  26. <td></td>
  27. </tr>
  28. <tr>
  29. <td></td>
  30. <td><input type="submit" value="登陆"></td>
  31. </tr>
  32. </tbody>
  33. </table>
  34. </form>
  35. </body>
  36. </html>

登陆:

  1. from django.shortcuts import render, redirect, reverse
  2. from .forms import LoginForm
  3. from django.contrib.auth import login, logout
  4. def my_login(request):
  5. if request.method == "GET":
  6. return render(request, 'login.html')
  7. if request.method == "POST":
  8. form = LoginForm(request.POST)
  9. if form.is_valid():
  10. phone = form.cleaned_data.get("phone")
  11. password = form.cleaned_data.get("password")
  12. remember = form.cleaned_data.get("remember")
  13. user = authenticate(request, username=phone, password=password)
  14. # authenticate验证
  15. if user and user.is_active: # 如果存在且不为黑名单
  16. # 在session表中登记信息
  17. login(request, user)
  18. if remember: # 是否有点"记住我"
  19. # 设置为None,则表示使用全局的默认时间(2周)
  20. request.session.set_expiry(None)
  21. else:
  22. # 浏览器结束即结束
  23. request.session.set_expiry(0)
  24. return HttpResponse("登陆成功")
  25. else:
  26. return HttpResponse("手机或密码错误")
  27. else:
  28. return redirect(reverse('login'))

注销

注销,或者说退出登录。通过django.contrib.auth.logout来实现。他会清理掉这个用户的session数据(表也会清除,类似request.session.flush())。

  1. from django.contrib.auth import logout
  2. def my_logout(request):
  3. logout(request)
  4. return HttpResponse("登出成功")

登录限制:使用装饰器

需要某个视图函数是需要经过登录后才能访问的。

通过django.contrib.auth.decorators.login_required装饰器来实现。

  1. from django.contrib.auth.decorators import login_required
  2. @login_required(login_url='/login/') # 如果验证失败,则跳转login_url指定的页面
  3. # 会传递 next= urls.py中视图函数对应的urls路径
  4. # 比如当前函数的urls路径为 two/profile/ 则传递 next=/two/prifle/ <-!!!没有多一个 /
  5. def profile(request):
  6. return HttpResponse("登陆成功才能看见")

/login/的视图函数中,判断是否有这个next查询字符串,决定是否再跳转到profile视图函数

  1. def my_login(request):
  2. # ...
  3. if user and user.is_active: # 如果存在且不为黑名单
  4. # request.session['user_id'] = user.id
  5. login(request, user)
  6. if remember:
  7. # 设置为None,则表示使用全局的默认时间(2周)
  8. request.session.set_expiry(None)
  9. else:
  10. request.session.set_expiry(0)
  11. next_url = request.GET.get('next') # 装饰器login_request修饰的函数跳转后会传递next查询字符串
  12. if next_url:
  13. return redirect(next_url) # 跳转回profile视图函数
  14. else:
  15. return HttpResponse("登陆成功")
  16. else:
  17. return HttpResponse("手机或密码错误")
  18. # ...