Django前后端分离之后端基础3

12 案例:登录_哔哩哔哩_bilibili   参考大佬的B站视频教程笔记

登录接口的实现会话机制成功后的信息保存:

  1. 生成随机字符串
  2. 返回到用户的浏览器的cookie中
  3. 存储到网站的session中  随机字符串+用户标识

中间件的使用,解决登录保护使未登录过的用户进行登录

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect


class AuthMiddleware(MiddlewareMixin):
    # 项目运行前的操作请求,钩子函数
    def process_request(self, request):
        # 0.排除那些不需要登录就能访问的页面
        #   request.path_info 获取当前用户请求的URL /login/
        if request.path_info in ["/login/", "/image/code/"]:
            return

        # 1.读取当前访问的用户的session信息,如果能读到,说明已登陆过,就可以继续向后走。
        info_dict = request.session.get("info")
        # print(info_dict)
        if info_dict:
            return

        # 2.没有登录过,重新回到登录页面
        return redirect('/login/')
# 注册app中间件
'myapp.middleware.auth.AuthMiddleware'

Form组件 - 主要作用:

1.生成html表单标签、数据校验

2.form = LoginForm(initial={'user':'xxx','password':'xxx'}) # Web页面默认值,字典类型

Form组件信息的配置

# form 组件配置
class LoginForm(BootStrapForm):
    username = forms.CharField(
        label="用户名",
        widget=forms.TextInput,
        required=True
    )
    password = forms.CharField(
        label="密码",
        widget=forms.PasswordInput(render_value=True), # 展示数据(加密点显示)
        required=True
    )

    code = forms.CharField(
        label="验证码",
        widget=forms.TextInput,
        required=True
    )

    def clean_password(self):  # 密码采用md5加密
        pwd = self.cleaned_data.get("password")
        return md5(pwd)

数据校验视图

def login(request):
    """ 登录 """
    if request.method == "GET":
        form = LoginForm()
        return render(request, 'login.html', {'form': form})

    form = LoginForm(data=request.POST)
    # form = LoginForm(initial={'user':'xxx','password':'xxx','code':'xxxx'})  # Web页面初始值
    if form.is_valid():
        # 验证成功,获取到的用户名和密码
        # {'username': 'wupeiqi', 'password': '123',"code":123}
        # 验证码的校验
        user_input_code = form.cleaned_data.pop('code')
        code = request.session.get('image_code', "")
        if code.upper() != user_input_code.upper():
            form.add_error("code", "验证码错误")
            return render(request, 'login.html', {'form': form})
        # 去数据库校验用户名和密码是否正确,获取用户对象、None
        # admin_object = models.Admin.objects.filter(username=xxx, password=xxx).first()
        admin_object = models.Admin.objects.filter(**form.cleaned_data).first()
        if not admin_object:
            form.add_error("password", "用户名或密码错误")
            # form.add_error("username", "用户名或密码错误")
            return render(request, 'login.html', {'form': form})

        # 用户名和密码正确
        # 网站生成随机字符串; 写到用户浏览器的cookie中;在写入到session中;
        request.session["info"] = {'id': admin_object.id, 'name': admin_object.username}
        # session可以保存7天
        request.session.set_expiry(60 * 60 * 24 * 7)

        return redirect("/admin/list/")

    return render(request, 'login.html', {'form': form})

登录页面login.html


ModelForm组件 - 特点:

  1. 校验数据,生成表单标签
  2. 使用obj直接保存数据到数据库,免去复杂的xxx.objects.create(xxx)
  3. 默认显示数据,对象类型

        obj=xxx.objects.filter(id=1).first()   

        obj=xxxModelForm(instance=obj)

  1. 依赖于数据库的model,减少字段的定义
    class Meta:
        model = xxx
        fields = ['username']
        # fields = "__all__"

 ModelForm组件

class UserModelForm(BootStrapModelForm):
    name = forms.CharField(
        min_length=3,
        label="用户名",
        widget=forms.TextInput(attrs={"class": "form-control"})
    )

    class Meta:
        model = models.UserInfo
        fields = ["name", "password", "age", 'account', 'create_time', "gender", "depart"]
        # fields = '__all__'

数据检验与保存

def user_model_form_add(request):
    """ 添加用户(ModelForm版本)"""
    if request.method == "GET":
        form = UserModelForm()
        return render(request, 'user_model_form_add.html', {"form": form})

    # 用户POST提交数据,数据校验。
    form = UserModelForm(data=request.POST)
    if form.is_valid():
        # 如果数据合法,保存到数据库
        # {'name': '123','account': Decimal('0'),'gender': 1, 'depart': }
        # print(form.cleaned_data)
        form.save()  # 同  models.UserInfo.objects.create(..)
        return redirect('/user/list/')

    # 校验失败(在页面上显示错误信息)
    return render(request, 'user_model_form_add.html', {"form": form})

 用户web页面user_add.html

新建用户

{% csrf_token %} {% for field in form %}
{{ field }} {{ field.errors.0 }}
{% endfor %}

验证码的保存在session会话中并设置过期时间

# 写入到自己的session中(以便于后续获取验证码再进行校验)
request.session['image_code'] = code_string
# 给Session设置60s超时
request.session.set_expiry(60)
# 校验
# 验证码的校验
user_input_code = form.cleaned_data.pop('code')
code = request.session.get('image_code', "")
if code.upper() != user_input_code.upper():
    form.add_error("code", "验证码错误")
    return render(request, 'login.html', {'form': form})

保存用户登录的信息到session并设置过期时间

# 网站生成随机字符串; 写到用户浏览器的cookie中;在写入到session中;
request.session["info"] = {'id': admin_object.id, 'name': admin_object.username}
# session可以保存7天
request.session.set_expiry(60 * 60 * 24 * 7)

用户密码的加密形式(即用户输入的密码是密钥加密和MD5加密后来进行和数据库中比对)

def md5(data_string): # SECRET_KEY + MD5 加密
    obj = hashlib.md5(settings.SECRET_KEY.encode('utf-8'))
    obj.update(data_string.encode('utf-8'))
    return obj.hexdigest()

用户注销功能的实现

def logout(request):
    """ 注销 """
    request.session.clear() # 清除session会话信息
    return redirect('/login/')

model中的choices字段的获取

# 在django中做的约束
gender_choices = ((1, "男"),(2, "女"),)
gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices)

 获取方法:get_字段名_display() 

queryset = models.UserInfo.objects.all()
for row in queryset:
   print(row.get_gender_display()) 

# 输出男或女

# [注意:row.get_gender_display在前端页面时不要加括号,django自动实现]

你可能感兴趣的:(django,python,后端)