[web development] 8. Django (3)

Tip: After the article is written, the table of contents can be automatically generated. For how to generate it, please refer to the help document on the right.


Preface

提示:这里可以添加本文要记录的大概内容:

For example: With the continuous development of artificial intelligence, machine learning technology is becoming more and more important. Many people have started learning machine learning. This article introduces the basic content of machine learning.


提示:以下是本篇文章正文内容,下面案例可供参考

1. Administrator

1. Table structure

First, define the Admin class under the models.py file, and use the djando command to generate the database table (python manage.py makemigrations; python manage.py migrate). Only the app01_admin data table exists under the database.

#models.py
class Admin(models.Model):
    """管理员"""
    username = models.CharField(verbose_name="用户名",max_length=32)
    password = models.CharField(verbose_name="密码",max_length=64)

    def __str__(self):
        return self.username      #连接表中所显示的内容

2. Add the navigation for the administrator account under the layout.html file

<li><a href="/admin/list/">管理员账户</a></li>

3.urls.py file (POST request passes nid)

     path('admin/list/', admin.admin_list),
     path('admin/add/', admin.admin_add),
     path('admin/<int:nid>/edit/', admin.admin_edit),
     path('admin/<int:nid>/delete/', admin.admin_delete),
     path('admin/<int:nid>/reset/', admin.admin_reset),

4.form.py file (password encryption, password confirmation, password reset is inconsistent with the original password requirements)

from django import forms
from django.core.exceptions import ValidationError

from app01 import models
from app01.utils.encrypt import md5
from app01.utils.bootstrap import BootstrapModelForm

class AdminModelForm(BootstrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        widget=forms.PasswordInput(render_value=True))

    class Meta:
        model = models.Admin
        fields = ["username", 'password', 'confirm_password']
        widgets = {
    
    
            "password": forms.PasswordInput(render_value=True)
            #render_value=True密码错误也不会置空
        }

    def clean_password(self):
        pwd = self.cleaned_data.get("password")
        return md5(pwd)

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get("password")
        confirm = md5(self.cleaned_data.get("confirm_password"))
        if confirm != pwd:
            raise ValidationError("密码不一致")
        # 返回的数值保存在数据库中
        return confirm

class AdminEditModelForm(BootstrapModelForm):
    class Meta:
        model = models.Admin
        fields = ['username']  # 只允许编辑用户名,其他信息不能编辑

class AdminResetModelForm(BootstrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        widget=forms.PasswordInput(render_value=True))

    class Meta:
        model = models.Admin
        fields = ["password", "confirm_password"]
        widgets = {
    
    
            "password": forms.PasswordInput(render_value=True)
        }

    def clean_password(self):
        pwd = self.cleaned_data.get("password")
        md5_pwd = md5(pwd)

        # 去数据库校验当前密码和输入密码是否一致
        exists = models.Admin.objects.filter(id=self.instance.pk, password=md5_pwd).exists()
        if exists:
            raise ValidationError("与之前密码一致")
        return md5_pwd

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get("password")
        confirm = md5(self.cleaned_data.get("confirm_password"))
        if confirm != pwd:
            raise ValidationError("密码不一致")
        # 返回的数值保存在数据库中
        return confirm

5.admin.py file

(Whether the user exists/logged in, search, paging, confirm that the edited object exists in the database before editing, display the information of the field before editing when editing, write the template file to transfer the title when adding the same page)

from django.shortcuts import render, redirect

from app01 import models
from app01.utils.pagination import Pagination
from app01.utils.form import AdminModelForm,AdminEditModelForm,AdminResetModelForm


def admin_list(request):
    """管理员列表"""
    
    """检查用户是否登录,已登录继续走下去,未登录,跳转到登录页面
    用户发来请求,获取cookie随机字符串,拿着随机字符串看session中有没有"""
   #是否登录
    info = request.session["info"]
    if not info:
        return redirect("/login/")
    # 搜索
    data_dict = {
    
    }
    search_data = request.GET.get('q', "")
    if search_data:
        data_dict["username__contains"] = search_data
    # 根据搜索条件去数据库获取
    queryset = models.Admin.objects.filter(**data_dict)
    # 分页
    page_object = Pagination(request, queryset, page_size=3)
    context = {
    
    
        'queryset': page_object.page_queryset,
        'page_string': page_object.html(),
        'search_data': search_data,
    }
    return render(request, "admin_list.html", context)

def admin_add(request):
    """添加管理员"""
    title = "新建管理员"
    if request.method == "GET":
        form = AdminModelForm()
        #change.html为添加模板
        return render(request, 'change.html', {
    
    "form": form, "title": title})
    form = AdminModelForm(data=request.POST)
    if form.is_valid():
        form.save()
        return redirect('/admin/list')
    return render(request, 'change.html', {
    
    "form": form, "title": title})

def admin_edit(request, nid):
    """编辑管理员"""
    row_object = models.Admin.objects.filter(id=nid).first()
    if not row_object:
        return render(request, "error.html", {
    
    "msg": "数据不存在"})
    title = "编辑管理员"

    if request.method == "GET":
        form = AdminEditModelForm(instance=row_object)  # 输入框内显示的默认值
        return render(request, 'change.html', {
    
    "form": form, "title": title})
    form = AdminEditModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect("/admin/list")
    return render(request, 'change.html', {
    
    "form": form, "title": title})

def admin_delete(request, nid):
    models.Admin.objects.filter(id=nid).delete()
    return redirect('/admin/list/')

def admin_reset(request, nid):
    """重置密码"""
    row_object = models.Admin.objects.filter(id=nid).first()
    if not row_object:
        return redirect('/admin/list/')
    title = "重置密码-{}".format(row_object.username)
    if request.method == "GET":
        form = AdminResetModelForm()
        return render(request, 'change.html', {
    
    "form": form, "title": title})
    form = AdminResetModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect("/admin/list/")
    return render(request, 'change.html', {
    
    "form": form, "title": title})

2. Middleware (implementing login verification)

#info is used to verify whether the user has logged in so that he can access other pages.
In other pages that require login to access, you must add:

#是否登录
    info = request.session["info"]
    if not info:
        return redirect("/login/")

1. The role of middleware

Actions can be performed before the request reaches the view function. This allows you to perform authentication , permission checks , logging, etc. before the request is processed.

Create the middleware directory in the appo01 directory and create the auth.py file
Insert image description here

2. Define middleware

#auth.py
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect

class AuthMiddleware(MiddlewareMixin):
    """中间件"""
    def process_request(selfself,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/")

3. Application middleware

And add the path to the middleware auth.py in MIDDLEWARE under the settings.py file
Insert image description here

4. Process_request method in middleware

#If there is no return value in the method (return None), continue to go backwards
#If there is a return value HttpResponse\render\redirect, no longer continue to execute backwards

3. Image verification code and login interface

1. Picture verification code

pip install pillow
def image_code(request):
    """生成图片验证码"""
    # 调用pillow函数,生成图片
    img, code_string = check_code()
    print(code_string)
    # 写入到自己的session中,以便后续获取验证码再进行校验
    request.session['imge_code'] = code_string
    # 给session设置60*60*24*7秒超时
    request.session.set_expiry(60 * 60 * 24 * 7)
    #内存文件BytesIO
    stream = BytesIO()
    img.save(stream, 'png')
    return HttpResponse(stream.getvalue())

2. Login interface

POST submission needs to add: {% csrf_token %}
to eliminate the browser's own prompt: add novalidate in the form

#html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .account {
      
      
            width: 450px;
            border: 1px solid gray;
            height: 400px;
            margin-left: auto;
            margin-right: auto;
            margin-top: 150px;
            padding: 40px 20px 40px 20px;
            border-radius: 5px;
            box-shadow: 5px 5px 5px #aaa;
        }

        .account h1 {
      
      
            text-align: center;
            margin-top: 5px;
        }
    </style>
</head>
<body>
<div class="account">
    <h1>用户登录</h1>
    {#    <form method="post" action = "{% url 'admin' %}">#}
    <form method="post" novalidate>
        {% csrf_token %}
        <div >
            <label>用户名</label>
            {
   
   { form.username }}
            <span style="color: red;">{
   
   { form.username.errors.0 }}</span>
        </div>
        <div class="form-group">
            <label>密码</label>
            {
   
   { form.password }}
            <span style="color: red;">{
   
   { form.password.errors.0 }}</span>

        </div>
        <div class="form-group"><!---->
                <div>
                    <label>图片验证码</label>
                </div>
                <div class="col-lg-7">
                    {
   
   { form.code }}
            <span style="color: red;">{
   
   { form.code.errors.0 }}</span>
                </div>
                <img data-v-66879da5="" alt="验证码"
                     src="/image/code/"
                     class="img-logo" style="margin-left: 20px">
            </div>
        <div>
            <button type="submit" class="btn btn-primary" style="margin-top: 18px;">登 录</button>
        </div>
    </form>

</div>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
class LoginForm(BootstrapForm):
#Form组件需要手动写字段
    username = forms.CharField(
        label="用户名",
        widget=forms.TextInput(),
        # widget=forms.TextInput(attrs={"class":"form-group"}),
        required=True  # 必填,不能为空

    )
    password = forms.CharField(
        label="密码",
        widget=forms.PasswordInput(render_value=True),
        required=True  # 必填,不能为空
    )
    code = forms.CharField(
        label="验证码",
        widget=forms.TextInput,
        required=True  # 必填,不能为空
    )
    class Meta:
        model = models.Admin
        fields = ['username', 'password']
    def clean_password(self):
        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)
    if form.is_valid():
        print(form.cleaned_data)#验证成功,获取用户名和密码
        user_input_code = form.cleaned_data.pop('code')
        code = request.session.get('imge_code')
        if code.upper() != user_input_code.upper():
            form.add_error("code", "验证码错误")  # 主动在password下添加错误提示
            return render(request, 'login.html', {
    
    "form": form})
        # 去数据库校验用户名和密码是否正确,获取用户对象
        admin_object = models.Admin.objects.filter(**form.cleaned_data).first()
        if not admin_object:
            form.add_error("password", "用户名或密码错误")  # 主动在password下添加错误提示
            return render(request, 'login.html', {
    
    "form": form})
        # 用户名和密码正确
        # 网站生成随机字符串,写到用户浏览器的cookie中,在写入到session中
        request.session["info"] = {
    
    "id": admin_object.id, "name": admin_object.username}
        #info用于验证用户是否登录过,以便能否访问其他页面
        return redirect("/admin/list/")
    return render(request, 'login.html', {
    
    "form": form})

4. Log out the user (log out)

def logout(request):
    """注销"""
    request.session.clear()
    return redirect('/login/')
登录完成,则{
    
    {
    
     request.session.info.name }}一定存在,可以直接传到html中

Guess you like

Origin blog.csdn.net/qq_46644680/article/details/132887512