关于django:Django开发0到1开发美多shop项目用户登录模块开发全md文档笔记附代码-文档

8次阅读

共计 7471 个字符,预计需要花费 19 分钟才能阅读完成。

本系列文章 md 笔记(已分享)次要探讨 django 商城我的项目相干常识。我的项目利用 Django 框架开发一套前后端不拆散的商城我的项目(4.0 版本)含代码和文档。性能包含前后端不拆散,不便 SEO。采纳 Django + Jinja2 模板引擎 + Vue.js 实现前后端逻辑,Nginx 服务器(反向代理)Nginx 服务器(动态首页、商品详情页、uwsgi 服务器(美多商场业务场景),后端服务:MySQL、Redis、Celery、RabbitMQ、Docker、FastDFS、Elasticsearch、Crontab,内部接口:容联云、QQ 互联、支付宝。

仓库里残缺材料代码:

请移步这里获取文档和代码

感兴趣的小伙伴能够自取哦,欢送大家点赞转发~


共 11 章,132 子模块

账号登录

用户名登录

1. 用户名登录逻辑剖析

2. 用户名登录接口设计

1. 申请形式

选项 计划
申请办法 POST
申请地址 /login/

2. 申请参数:表单

参数名 类型 是否必传 阐明
username string 用户名
password string 明码
remembered string 是否记住用户

3. 响应后果:HTML

字段 阐明
登录失败 响应谬误提醒
登录胜利 重定向到首页

3. 用户名登录接口定义

class LoginView(View):
    """用户名登录"""

    def get(self, request):
        """
        提供登录界面
        :param request: 申请对象
        :return: 登录界面
        """
        pass

    def post(self, request):
        """
        实现登录逻辑
        :param request: 申请对象
        :return: 登录后果
        """
        pass

4. 用户名登录后端逻辑

class LoginView(View):
    """用户名登录"""

    def get(self, request):
        """
        提供登录界面
        :param request: 申请对象
        :return: 登录界面
        """return render(request,'login.html')

    def post(self, request):
        """
        实现登录逻辑
        :param request: 申请对象
        :return: 登录后果
        """
        # 承受参数
        username = request.POST.get('username')
        password = request.POST.get('password')
        remembered = request.POST.get('remembered')

        # 校验参数
        # 判断参数是否齐全
        if not all([username, password]):
            return http.HttpResponseForbidden('短少必传参数')

        # 判断用户名是否是 5 -20 个字符
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return http.HttpResponseForbidden('请输出正确的用户名或手机号')

        # 判断明码是否是 8 -20 个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('明码起码 8 位,最长 20 位')

        # 认证登录用户
        user = authenticate(username=username, password=password)
        if user is None:
            return render(request, 'login.html', {'account_errmsg': '用户名或明码谬误'})

        # 实现状态放弃
        login(request, user)
        # 设置状态放弃的周期
        if remembered != 'on':
            # 没有记住用户:浏览器会话完结就过期
            request.session.set_expiry(0)
        else:
            # 记住用户:None 示意两周后过期
            request.session.set_expiry(None)

        # 响应登录后果
        return redirect(reverse('contents:index'))

5. 常识要点

  1. 登录的核心思想:认证和状态放弃

    • 通过用户的认证,确定该登录用户是美多商场的注册用户。
    • 通过状态放弃缓存用户的惟一标识信息,用于后续是否登录的判断。

多账号登录

  • Django 自带的用户认证后端默认是应用用户名实现用户认证的。
  • 用户认证后端地位:django.contrib.auth.backends.ModelBackend。
  • 如果想实现用户名和手机号都能够认证用户,就须要自定义用户认证后端。
  • 自定义用户认证后端步骤

    • 在 users 利用中新建 utils.py 文件
    • 新建类,继承自 ModelBackend
    • 重写认证 authenticate()办法
    • 别离应用用户名和手机号查问用户
    • 返回查问到的用户实例

1. 自定义用户认证后端

users.utils.py

from django.contrib.auth.backends import ModelBackend
import re
from .models import User


def get_user_by_account(account):
    """
    依据 account 查问用户
    :param account: 用户名或者手机号
    :return: user
    """
    try:
        if re.match('^1[3-9]\d{9}$', account):
            # 手机号登录
            user = User.objects.get(mobile=account)
        else:
            # 用户名登录
            user = User.objects.get(username=account)
    except User.DoesNotExist:
        return None
    else:
        return user


class UsernameMobileAuthBackend(ModelBackend):
    """自定义用户认证后端"""

    def authenticate(self, request, username=None, password=None, **kwargs):
        """
        重写认证办法,实现多账号登录
        :param request: 申请对象
        :param username: 用户名
        :param password: 明码
        :param kwargs: 其余参数
        :return: user
        """
        # 依据传入的 username 获取 user 对象。username 能够是手机号也能够是账号
        user = get_user_by_account(username)
        # 校验 user 是否存在并校验明码是否正确
        if user and user.check_password(password):
            return user

2. 配置自定义用户认证后端

1.Django 自带认证后端源码

2. 配置自定义用户认证后端

  
  
# 指定自定义的用户认证后端
  
  
AUTHENTICATION_BACKENDS = ['users.utils.UsernameMobileAuthBackend']

3. 测试自定义用户认证后端

4. 常识要点

  1. Django 自带的用户认证零碎只会应用用户名去认证一个用户。

    • 所以咱们为了实现多账号登录,就能够自定义认证后端,采纳其余的惟一信息去认证一个用户。

首页用户名展现

1. 首页用户名展现计划

计划一

  • 模板中 request 变量间接渲染用户名
  • 毛病:不不便做首页动态化
{% if user.is_authenticated %}
    <div class="login_btn fl">
        欢迎您:<em>{{user.username}}</em>
        <span>|</span>
        <a href="#"> 退出 </a>
    </div>
    {% else %}
    <div class="login_btn fl">
        <a href="login.html"> 登录 </a>
        <span>|</span>
        <a href="register.html"> 注册 </a>
    </div>
{% endif %}

计划二

  • 发送 ajax 申请获取用户信息
  • 毛病:须要发送网络申请
<div class="login_btn fl">
    {# ajax 渲染 #}
</div>

计划三

  • Vue 读取 cookie 渲染用户信息
<div v-if="username" class="login_btn fl">
    欢迎您:<em>[[username]]</em>
    <span>|</span>
    <a href="#"> 退出 </a>
</div>
<div v-else class="login_btn fl">
    <a href="login.html"> 登录 </a>
    <span>|</span>
    <a href="register.html"> 注册 </a>
</div>

论断:

  • 比照此三个计划,咱们在本我的项目中抉择 计划三

实现步骤:

  • 注册或登录后,用户名写入到 cookie
  • Vue 渲染主页用户名

2. 用户名写入到 cookie

  
  
# 响应注册后果
  
  
response = redirect(reverse('contents:index'))

  
  
# 注册时用户名写入到 cookie,有效期 15 天
  
  
response.set_cookie('username', user.username, max_age=3600 * 24 * 15)

return response
  
  
# 响应登录后果
  
  
response = redirect(reverse('contents:index'))

  
  
# 登录时用户名写入到 cookie,有效期 15 天
  
  
response.set_cookie('username', user.username, max_age=3600 * 24 * 15)

return response

3. Vue 渲染首页用户名

1.index.html

<div v-if="username" class="login_btn fl">
    欢迎您:<em>[[username]]</em>
    <span>|</span>
    <a href="#"> 退出 </a>
</div>
<div v-else class="login_btn fl">
    <a href="login.html"> 登录 </a>
    <span>|</span>
    <a href="register.html"> 注册 </a>
</div>

2.index.js

mounted(){
    // 获取 cookie 中的用户名
    this.username = getCookie('username');
},

退出登录

1. logout()办法介绍

  1. 退出登录:

    • 回顾登录:将通过认证的用户的惟一标识信息,写入到以后 session 会话中
    • 退出登录:正好和登录相同(清理 session 会话信息)
  2. logout()办法:

    • Django 用户认证零碎提供了 logout() 办法
    • 封装了清理 session 的操作,帮忙咱们疾速实现登出一个用户
  3. logout()地位:

    • django.contrib.auth.__init__.py文件中
logout(request)

2. logout()办法应用

class LogoutView(View):
    """退出登录"""

    def get(self, request):
        """实现退出登录逻辑"""
        # 清理 session
        logout(request)
        # 退出登录,重定向到登录页
        response = redirect(reverse('contents:index'))
        # 退出登录时革除 cookie 中的 username
        response.delete_cookie('username')

        return response

3. 常识要点

  1. 退出登录的核心思想就是清理登录时缓存的状态放弃信息。
  2. 因为首页中用户名是从 cookie 中读取的。所以退出登录时,须要将 cookie 中用户名革除。

判断用户是否登录

1. 展现用户核心界面

class UserInfoView(View):
    """用户核心"""

    def get(self, request):
        """提供个人信息界面"""
        return render(request, 'user_center_info.html')

需要:

  • 当用户登录后,能力拜访用户核心。
  • 如果用户未登录,就不容许拜访用户核心,将用户疏导到登录界面。

实现计划:

  • 须要判断用户是否登录。
  • 依据是否登录的后果,决定用户是否能够拜访用户核心。

2. is_authenticate 判断用户是否登录

介绍:

  • Django 用户认证零碎提供了办法 request.user.is_authenticated() 来判断用户是否登录。
  • 如果通过登录验证则返回True。反之,返回False
  • 毛病:登录验证逻辑很多中央都须要,所以该代码须要反复编码好屡次。
class UserInfoView(View):
    """用户核心"""

    def get(self, request):
        """提供个人信息界面"""
        if request.user.is_authenticated():
            return render(request, 'user_center_info.html')
        else:
            return redirect(reverse('users:login'))

3. login_required 装璜器 判断用户是否登录

  • Django 用户认证零碎提供了装璜器 login_required 来判断用户是否登录。

    • 外部封装了is_authenticate
    • 地位:django.contrib.auth.decorators
  • 如果通过登录验证则进入到视图外部,执行视图逻辑。
  • 如果未通过登录验证则被重定向到 LOGIN_URL 配置项指定的地址。

    • 如下配置:示意当用户未通过登录验证时,将用户重定向到登录页面。

      LOGIN_URL = '/login/'

1. 装璜 as_view() 办法返回值

提醒:

  • login_required 装璜器 能够间接装璜函数视图,然而本我的项目应用的是类视图。
  • as_view()办法的返回值就是将类视图转成的函数视图。

论断:

  • 要想应用 login_required 装璜器 装璜类视图,能够间接的装璜 as_view() 办法的返回值,以达到预期成果。
url(r'^info/$', login_required(views.UserInfoView.as_view()), name='info'),
class UserInfoView(View):
    """用户核心"""

    def get(self, request):
        """提供个人信息界面"""
        return render(request, 'user_center_info.html')

2. 定义 View 子类封装login_required 装璜器

  • 提醒:LoginRequired(object)依赖于视图类View,复用性很差。
url(r'^info/$', views.UserInfoView.as_view(), name='info'),
class LoginRequired(View):
  """验证用户是否登陆"""

  @classmethod
  def as_view(cls, **initkwargs):
      # 自定义 as_view()办法中,调用父类的 as_view()办法
      view = super().as_view()
      return login_required(view)


class UserInfoView(LoginRequired):
    """用户核心"""

    def get(self, request):
        """提供个人信息界面"""
        return render(request, 'user_center_info.html')

3. 定义 obejct 子类封装login_required 装璜器

  • 提醒:LoginRequired(object)不依赖于任何视图类,复用性更强。
url(r'^info/$', views.UserInfoView.as_view(), name='info'),
class LoginRequired(object):
  """验证用户是否登陆"""

  @classmethod
  def as_view(cls, **initkwargs):
      # 自定义 as_view()办法中,调用父类的 as_view()办法
      view = super().as_view()
      return login_required(view)


class UserInfoView(LoginRequired, View):
    """用户核心"""

    def get(self, request):
        """提供个人信息界面"""
        return render(request, 'user_center_info.html')

4. 定义验证用户是否登录扩大类

  • 提醒:定义扩大类不便我的项目中导入和应用(meiduo_mall.utils.views.py)
class LoginRequiredMixin(object):
  """验证用户是否登录扩大类"""

  @classmethod
  def as_view(cls, **initkwargs):
      # 自定义的 as_view()办法中,调用父类的 as_view()办法
      view = super().as_view()
      return login_required(view)
class UserInfoView(LoginRequiredMixin, View):
    """用户核心"""

    def get(self, request):
        """提供个人信息界面"""
        return render(request, 'user_center_info.html')

4. 登录时 next 参数的应用

1.next 参数的成果

http://127.0.0.1:8000/login/?next=/info/

2.next 参数的作用

  • 由 Django 用户认证零碎提供,搭配 login_required 装璜器 应用。
  • 记录了用户未登录时拜访的地址信息,能够帮忙咱们实现在用户登录胜利后间接进入未登录时拜访的地址。
  
  
# 响应登录后果
  
  
next = request.GET.get('next')
if next:
    response = redirect(next)
else:
    response = redirect(reverse('contents:index'))

5. 常识要点

  1. 判断用户是否登录仍然应用状态放弃信息实现。
  2. 我的项目中很多接口都是须要用户登录能力拜访的,所以为了不便编码,咱们将判断用户登录的操作封装到装璜器中。
  3. 登录时 next 参数的作用是为了不便用户从哪里进入到登录页面,登录胜利后就回到哪里。

QQ 登录

未完待续,同学们请期待下一期

仓库里残缺材料代码:

请移步这里获取文档和代码

感兴趣的小伙伴能够自取哦,欢送大家点赞转发~

正文完
 0