python Django web框架的基础知识总结

98 阅读47分钟

Django框架的开始

首先我们的前端是如何实现从后端提取数据的:就是通过的我们的前端向服务器提供要求,后端通过我们的前端的要求实现返回数据给前端
​
为什么我们使用Django框架,就是因为我们需要使用这个框架来实现完成我们的web程序的开发

搭建服务器的方法

# 实现搭建服务器的方法是:先使用我们的socket这个套接字来实现基本的功能
import socket# 然后创建我们的socket对象,一般来说的话,默认是使用的我们的TCP协议来实现的
socket = socket.socket()
​
# 然后实现绑定我们的地址和端口号
socket.bind(('127.0.0.1', 9999))
​
# 被动等待我们的客户端的连接
socket.listen(5)
​
# 通过accept实现我们的接收客户端的连接,同时会返回两个参数,
# 一个是我们的那个套接字,一个是我们的地址,一般的话实现就是实现于我们的循环中
while True:
    conn, addr = socket.accept()
​
    # 开始实现接收客户端传递过来的数据,同时实现我们的传递一个参数,来实现指定接收我们的信息大小
    data = conn.recv(1024)
    print(data)
​
    # 通过send方法给我们的客户端传递数据
    conn.send("hello world".encode("utf-8"))  # 或者说通过我们的那个b来实现转换为二进制形式
​
    # 最后实现我们的那个关闭服务
    # 首先我们使用的话,就先启动我们的服务端,然后等待客户端的连接
    # 所有的浏览器都是可以实现那个充当客户端使用的:直接输入ip地址加端口号就行了:127.0.0.1:9999
​
    # 注意我们的话,要记住遵循我们的http协议的内容,浏览器才会有响应
    conn.close()

http协议的基本格式

http协议的基本格式的话,分为请求数据的格式和响应数据的格式
​
1.http请求数据的格式:
  请求首行:请求的http的版本号和请求的方式
  请求头:就是一大推键值对,就是一些请求数据
  空白行
  请求体:get含有请求体,post请求才含有请求体
​
2.http响应数据的格式:
  相应首行:http版本号,响应状态码
  响应头:一大推键值对
  空白行
  响应体:就是服务端的一些响应数据

服务器向前端传送普通的文本的操作

# 实现搭建服务器的方法是:先使用我们的socket这个套接字来实现基本的功能
import socket# 然后创建我们的socket对象,一般来说的话,默认是使用的我们的TCP协议来实现的
socket = socket.socket()
​
# 然后实现绑定我们的地址和端口号
socket.bind(('127.0.0.1', 9999))
​
# 被动等待我们的客户端的连接
socket.listen(5)
​
# 通过accept实现我们的接收客户端的连接,同时会返回两个参数,
# 一个是我们的那个套接字,一个是我们的地址,一般的话实现就是实现于我们的循环中
while True:
    conn, addr = socket.accept()
​
    # 开始实现接收客户端传递过来的数据,同时实现我们的传递一个参数,来实现指定接收我们的信息大小
    data = conn.recv(1024)
    print(data)
​
    # 响应首行:
    conn.send(b"HTTP/1.1 200 ok \r\n\r\n")
    # 响应头信息
    # conn.send(b"\r\n")
    # 空白行
    # conn.send(b"/r/n")
    # 通过send方法给我们的客户端传递数据,响应体数据
    conn.send(b"<h1>hello world<h1>")  # 或者说通过我们的那个b来实现转换为二进制形式
​
    # 最后实现我们的那个关闭服务
    # 首先我们使用的话,就先启动我们的服务端,然后等待客户端的连接
    # 所有的浏览器都是可以实现那个充当客户端使用的:直接输入ip地址加端口号就行了:127.0.0.1:9999
​
    # 注意我们的话,要记住遵循我们的http协议的内容,浏览器才会有响应
    conn.close()

服务器向前端返回html文件内容

# 实现搭建服务器的方法是:先使用我们的socket这个套接字来实现基本的功能
import socket
​
# 然后创建我们的socket对象,一般来说的话,默认是使用的我们的TCP协议来实现的
socket = socket.socket()
​
# 然后实现绑定我们的地址和端口号
socket.bind(('127.0.0.1', 9999))
​
# 被动等待我们的客户端的连接
socket.listen(5)
​
# 通过accept实现我们的接收客户端的连接,同时会返回两个参数,
# 一个是我们的那个套接字,一个是我们的地址,一般的话实现就是实现于我们的循环中
while True:
    conn, addr = socket.accept()
​
    # 开始实现接收客户端传递过来的数据,同时实现我们的传递一个参数,来实现指定接收我们的信息大小
    data = conn.recv(1024)
    print(data)
​
    # 响应首行:
    conn.send(b"HTTP/1.1 200 ok \r\n\r\n")
    # 响应头信息
    # conn.send(b"\r\n")
    # 空白行
    # conn.send(b"/r/n")
    # 通过send方法给我们的客户端传递数据,响应体数据
    with open("text.html", "r", encoding="utf-8") as f:
        data = f.read()
    conn.send(data)
    # 或者说通过我们的那个b来实现转换为二进制形式
    # 或者说我们通过那个读取一个文件来返回我们的数也是可以的
​
    # 最后实现我们的那个关闭服务
    # 首先我们使用的话,就先启动我们的服务端,然后等待客户端的连接
    # 所有的浏览器都是可以实现那个充当客户端使用的:直接输入ip地址加端口号就行了:127.0.0.1:9999
​
    # 注意我们的话,要记住遵循我们的http协议的内容,浏览器才会有响应
    conn.close()

服务器向前端返回数据库中的内容

# 实现搭建服务器的方法是:先使用我们的socket这个套接字来实现基本的功能
import socket
import pymysql
import json
​
# 然后创建我们的socket对象,一般来说的话,默认是使用的我们的TCP协议来实现的
socket = socket.socket()
​
# 然后实现绑定我们的地址和端口号
socket.bind(('127.0.0.1', 9999))
​
# 被动等待我们的客户端的连接
socket.listen(5)
​
# 开始实现连接数据库中的数据
def get_data():
    db_conn = pymysql.connect(
        host = "127.0.0.1", # 主机名
        user = "juwenzhang",  # 用户名
        password = "451674",  # 数据库密码
        database = "db_name",  # 数据库名称
        charset = "utf8"  # 字符编码
    )
​
    # 数据库的操作是通过的我们的游标(指针)来实现操作的
    cursor = db_conn.cursor()  # 不传入参数的时候,默认的是元组的格式,如果说想要查询字典的格式
    sql = """select * from users;"""
​
    # 通过游标对象来实现执行我们的sql语句
    cursor.execute(sql)
​
    # 通过fetchall来实现返回我们的所有内容
    data = cursor.fetchall()
​
    db_conn.close()
​
    return json.dumps(data, ensure_ascii=False).encode('utf-8')
​
# 通过accept实现我们的接收客户端的连接,同时会返回两个参数,
# 一个是我们的那个套接字,一个是我们的地址,一般的话实现就是实现于我们的循环中
while True:
    conn, addr = socket.accept()
​
    # 开始实现接收客户端传递过来的数据,同时实现我们的传递一个参数,来实现指定接收我们的信息大小
    data = conn.recv(1024)
    print(data)
​
    # 响应首行:
    conn.send(b"HTTP/1.1 200 ok \r\n\r\n")
    # 响应头信息
    # conn.send(b"\r\n")
    # 空白行
    # conn.send(b"/r/n")
    # 通过send方法给我们的客户端传递数据,响应体数据
    conn.send(get_data())  # 或者说通过我们的那个b来实现转换为二进制形式
    # 或者说我们通过那个读取一个文件来返回我们的数也是可以的
​
    # 最后实现我们的那个关闭服务
    # 首先我们使用的话,就先启动我们的服务端,然后等待客户端的连接
    # 所有的浏览器都是可以实现那个充当客户端使用的:直接输入ip地址加端口号就行了:127.0.0.1:9999
​
    # 注意我们的话,要记住遵循我们的http协议的内容,浏览器才会有响应
    conn.close()
# 实现搭建服务器的方法是:先使用我们的socket这个套接字来实现基本的功能
import socket
import pymysql
import json
​
# 然后创建我们的socket对象,一般来说的话,默认是使用的我们的TCP协议来实现的
socket = socket.socket()
​
# 然后实现绑定我们的地址和端口号
socket.bind(('127.0.0.1', 9999))
​
# 被动等待我们的客户端的连接
socket.listen(5)
​
# 开始实现连接数据库中的数据
def get_data():
    try:
        db_conn = pymysql.connect(
            host="127.0.0.1",  # 主机名
            user="juwenzhang",  # 用户名
            password="451674",  # 数据库密码
            database="db_name",  # 数据库名称
            charset="utf8"  # 字符编码
        )
​
        # 数据库的操作是通过的我们的游标(指针)来实现操作的
        cursor = db_conn.cursor()  # 不传入参数的时候,默认的是元组的格式,如果说想要查询字典的格式
        sql = """select * from users;"""
​
        # 通过游标对象来实现执行我们的sql语句
        cursor.execute(sql)
​
        # 通过fetchall来实现返回我们的所有内容
        data = cursor.fetchall()
​
        db_conn.close()
​
        return json.dumps(data, ensure_ascii=False).encode('utf-8')
    except Exception as e:
        return json.dumps({'error 数据出错': str(e)}, ensure_ascii=False).encode('utf-8')
    finally:
        return b"databases error"
​
# 通过accept实现我们的接收客户端的连接,同时会返回两个参数,
# 一个是我们的那个套接字,一个是我们的地址,一般的话实现就是实现于我们的循环中
while True:
    conn, addr = socket.accept()
​
    # 开始实现接收客户端传递过来的数据,同时实现我们的传递一个参数,来实现指定接收我们的信息大小
    data = conn.recv(1024)
    print(data)
​
    # 响应首行:
    conn.send(b"HTTP/1.1 200 ok \r\n\r\n")
    # 响应头信息
    # conn.send(b"\r\n")
    # 空白行
    # conn.send(b"/r/n")
    # 通过send方法给我们的客户端传递数据,响应体数据
    conn.send(get_data())  # 或者说通过我们的那个b来实现转换为二进制形式
    # 或者说我们通过那个读取一个文件来返回我们的数也是可以的
​
    # 最后实现我们的那个关闭服务
    # 首先我们使用的话,就先启动我们的服务端,然后等待客户端的连接
    # 所有的浏览器都是可以实现那个充当客户端使用的:直接输入ip地址加端口号就行了:127.0.0.1:9999
​
    # 注意我们的话,要记住遵循我们的http协议的内容,浏览器才会有响应
    conn.close()
# 实现搭建服务器的方法是:先使用我们的socket这个套接字来实现基本的功能
import socket
import pymysql
import json
​
# 然后创建我们的socket对象,一般来说的话,默认是使用的我们的TCP协议来实现的
socket = socket.socket()
​
# 然后实现绑定我们的地址和端口号
socket.bind(('127.0.0.1', 9999))
​
# 被动等待我们的客户端的连接
socket.listen(5)
​
# 开始实现连接数据库中的数据
def get_data():
    try:
        db_conn = pymysql.connect(
            host="127.0.0.1",  # 主机名
            user="juwenzhang",  # 用户名
            password="451674",  # 数据库密码
            database="db_name",  # 数据库名称
            charset="utf8"  # 字符编码
        )
​
        # 数据库的操作是通过的我们的游标(指针)来实现操作的
        cursor = db_conn.cursor()  # 不传入参数的时候,默认的是元组的格式,如果说想要查询字典的格式
        sql = """select * from users;"""
​
        # 通过游标对象来实现执行我们的sql语句
        cursor.execute(sql)
​
        # 通过fetchall来实现返回我们的所有内容
        data = cursor.fetchall()
​
        db_conn.close()
​
        return json.dumps(data, ensure_ascii=False).encode('utf-8')
    except Exception as e:
        return json.dumps({'error 数据出错': str(e)}, ensure_ascii=False).encode('utf-8')
    finally:
        return b"databases error"
​
# 通过accept实现我们的接收客户端的连接,同时会返回两个参数,
# 一个是我们的那个套接字,一个是我们的地址,一般的话实现就是实现于我们的循环中
while True:
    conn, addr = socket.accept()
​
    # 开始实现接收客户端传递过来的数据,同时实现我们的传递一个参数,来实现指定接收我们的信息大小
    data = conn.recv(1024)
    # 实现将我们的数据实现解码,然后分割
    data01 = data.decode('utf-8').split(" ")
    print(data)
    print(data01[1])
​
    # 响应首行:
    conn.send(b"HTTP/1.1 200 ok \r\n\r\n")
    # 响应头信息
    # conn.send(b"\r\n")
    # 空白行
    # conn.send(b"/r/n")
    # 通过send方法给我们的客户端传递数据,响应体数据
    conn.send(str(get_data()).encode("gbk"))  # 或者说通过我们的那个b来实现转换为二进制形式
    # 或者说我们通过那个读取一个文件来返回我们的数也是可以的
​
    # 最后实现我们的那个关闭服务
    # 首先我们使用的话,就先启动我们的服务端,然后等待客户端的连接
    # 所有的浏览器都是可以实现那个充当客户端使用的:直接输入ip地址加端口号就行了:127.0.0.1:9999
​
    # 注意我们的话,要记住遵循我们的http协议的内容,浏览器才会有响应
    conn.close()
​
# 首先我们的程序的话是含有那个服务器程序和客户端程序的
# 然后后端的完成就是通过我们的服务器程序的开发,前端就是实现的我们的客户端程序的开发

Django的基本学习

Django的话实现的就是我们的服务器程序和应用程序
python web 程序就是实现的我们的那个这两个部分

服务器程序就是实现的对socket实现的封装,并且在请求的时候,对请求的数据实现整理
应用程序的话,负责对我们的具体的逻辑的处理
所以说为了方便我们的开发,就出现了众多的web框架,Django/ flask等等
最后的话,我们实现的就是那个使用我们的socket的实现

python中的主流的学习的web框架: Django / flask / tornado
Django:大而全,就是功能多并且全面
flask: 小而精,第三方模块十分多
tornado: 异步非阻塞的框架知识,就是支持高并发,支持开发游戏的服务器

我们是可以实现将我们web框架拆分为三个部分:
1.socket服务器的开发
2.路径和函数的匹配关系(路由匹配)
3.模板语法,实现我们将数据插入我们的那个html模板中,就是实现我们将py的变量名实现插入我们的html中去

Django: socket:wsgiref这个服务器
        路由匹配: 自己写的
        模板语法: 自己写的
        
flask: socket: 使用的别人的
       路由匹配: 自己写的
       模板语法: jinja2
       
tornade: 就是啥都是自己写的(裂开)


注意事项: 如果想要计算机正常启动Django项目,从计算机名称开始到文件的名称都不可以使用中文
         Django的话,运行的时候,就是实现的只运行一个py文件
         python的解析器的使用的版本不要使用高版本,接下来使用的Django的版本是我们的2.2.12,一般的话高版本的不稳定
         安装:Django: pip install django==2.2.12
因为我们实现的就是将不同的功能存放在不同的文件中实现不同的业务逻辑的实现

业务核心逻辑存放的文件:views.py
对应关系(后缀和需要学习的函数): urls.py

Django 的基本操作

Django 命令行操作
首先先切换到想要创建项目的目录中:cd D:
然后实现创建属于自己的想要的创建的目录下面
​
创建django项目: django-admin startproject 项目名   ---- manage.py就是我们的整个项目的启动文件
               启动django项目的话,就要切换到我们的项目路径下面: python manage.py runserver
               
               如果遇到环境问题:那么可以在正确的目录下面实现使用 pip install virtualenvwrapper-win
               同时我们的创建的时候,我们是可以实现创建我们的一些那个app目录的,这个是用来实现完成每一个特定的功能的
               1.创建app的方法是: python manage.py startapp app名称
               2.将app的路径添加到配置文件中:settings.py中寻找:INSTALLED_APPS,添加app
               templates: 这个目录下面就是实现的存放我们的html文件的
               'DIRS': [os.path.join(BASE_DIR, 'templates')],
Django settings.py配置文件介绍
BASE_DIR: 就是获取项目的根目录路径
DEBUG: 用于实现配置我们的Django的启动项目的模式的,True表示在开发环境中处于调试模式,False表示在运行在生产环境中
ALLOWED_HOSTS: 设置允许被访问本项目的主机,[]空列表表示的只有本机在可以访问,就是DEBUG为True的时候使用
                                      ["*"] 表示人格主机才可以访问
                                      ["地址一", "地址二"]: 就是我们的列表中的这两个地址才可以实现访问
INSTALLED_APPS: 就是实现注册我们的app,注册后我们才可以实现使用这个功能
MIDDLEWARE: 中间件的设置
ROOT_URLCONF: 就是我们的根页面,首先实现的访问的就是我们的这个路径
TEMPLATES: 就是用于存储html文档的路径
WSGI_APPLICATION: 就是我们的服务器的配置
DATABASES: 数据库
URL 统一资源定位符
用于表示的就是互联网上的某个资源的地址(网址)
互联网上的每个文件都含有唯一的url
http协议的默认端口为80,可以省略不写
​
一般的格式: 协议类型://域名[:端口号]/路径[?query][#fragment]
​
urls.py 文件中实现的功能就是实现的将我们的路径和函数实现一一匹配,匹配成功,那么我们就可以实现调用对应的函数
Django响应的三个必备内容
HttpResponse: 返回给我们的浏览器内容就是我们的字符串
render: 实现的是将我们的html文件实现返回给页面
redirect: 实现的是重定向(就是会实现跳转其他的页面)
注意我们的主要的功能是写在我们的那个view.py中的
​
path("home/", views.home),
​
# request 就是用来试下接收请求的
def home(request):
    return HttpResponse("hello world")
from django.shortcuts import render, HttpResponse, redirect

# Create your views here.

def home(request):
    return HttpResponse("hello world")

def about(request):
    return render(request, "index.html")

def content(request):
    return redirect("https://www.baidu.com")
urlpatterns = [
    path('admin/', admin.site.urls),
    path("home/", views.home),
    path("about/", views.about),
    path("content/", views.content),
]
Django 的路由配置
就是在我们的项目中的那个urls.py中实现的

首先的话,我们的这个函数实现的就是我们的path()

path(路由配置, 视图函数, name)
路由配置就是我们的字符串类型,匹配的请求路径
视图函数: 就是我们的视图函数对应的那个视图函数的名称
name: 实现为我们的地址别名(模板中的地址反向解析的时候使用的)
Django 静态资源
注意我们的静态资源文件的话,能够直接调用使用的文件(js,css,bootstrap),必须放在那个static目录的下面
然后我们是可以在这个下面实现基本的那个分文件的: js目录, css目录, image目录

同时有的时候,我们还需要在我们的那个settings.py中添加一个语句
STATICFILES_DIRS=[os.path.join(BASE_DIR, "static")]

STATIC_URL = '/static/' 但是注意即使是使用那个拼接我们的资源的路径,我们还是需要实现基本的那个加入这个令牌的,课修改

模板语法: {% 导入的路径 %}

"{% static '路径' %}"

image-20240730061445538

form中的action参数:就是书写的发起请求的路径,请求到路径路径后,就触发对应的后端函数,返回相应的数据
				  不写的时候,就是向我们的当前文件所在的位置提交数据信息
				  全写url: 就是向我们的这个url提交信息
				  只写后缀:就是向我们的当前的服务器提交数据信息的
       method参数:就是实现的我们的请求方法

Django的路由层

开始讲解我们的每个函数中的request参数的实际意义

首先我们的request就是我们的前端发送过来的请求

其中包含的属性含有method,这个就是我们的前端向后端发送过来的请求方法

Django request的常用的方法

request.method 就是用来实现的是我们的前端的请求方式

==============================================================================================
request.POST 就是用户的post请求实现的提交的普通数据

request.POST.get() 这个就是实现的是活取的是POST请求的时候实现的最后一个元素的值

request.POST.getlist() 就是实现的是活取我们的所有的值,返回的是一个字典
==============================================================================================

==============================================================================================
request.GET 就是用户的GET请求实现的提交的普通数据

request.GET.get() 这个就是实现的是活取的是GET请求的时候实现的最后一个元素的值

request.GET.getlist() 就是实现的是活取我们的所有的值,返回的是一个字典
def login(request):
    if request.method == "post" or request.method == "POST":
        print(request.POST,"\n")
        print(request.POST.get())
        return HttpResponse("post请求的登录页面")
    else:
        return render(request, "login.html")
    
==============================================================================================
为了实现防止
CSRF的攻击:
<form action="" method="post">{% csrf_token %}
或者说我们就在setting.py文件中添加:
CSRF_TRUSTED_ORIGINS

Django的连接数据库

连接数据库之前我们首先需要做的就是改变我们的setting.py中的DATABASES的设置:
​
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME' : 'your_database_name',
        'USER' : 'your_user_name',
        'PASSWORD' : 'your_password',
        'HOST' : '127.0.0.1',
        'PORT' : '3306',
        'CHARSET': 'utf8'
    }
}
=============================================================================================
​
然后我们的操作数据库就可以实现使用django中的orm方法来实现基本的操作数据库
orm ---- object relative map 的对象关系映射实现的连接数据库
类---表
对象---记录
对象属性---记录某个字段对应的某个值
首先我们的数据库的操作的地就是在models.py
​
​
from django.db import models
​
# Create your models here.
# 首先先实现继承关系
class User(models.Model):
    # 就是一一对应的关系,就是映射
    # 就是实现的是id int primary key auto_increment
    id = models.AutoField(primary_key=True)
    # username varchar(24)
    name = models.CharField(max_length=24)
    # password varchar(24)
    password = models.CharField(max_length=24)
    
    
=============================================================================================
实现迁移数据库: 命令行中的运行
​
python manage.py makemigrations  # 就是实现的将我们的操作记录到migration文件夹中
​
python ../manage.py migrate  # 就是实现将我们的python运行于数据库中,就是迁移操作,实现的是同步
​
pip install mysqlclient  # 实现操作mysql数据库的时候,我们可能会要求安装这个
​
python.exe -m pip install --upgrade pip  # 实现的是更新pip安装包
​
执行完迁移操作后,数据库中就会出现很多的表
​
​
==============================================================================================
实现基本的用户登录的校验
​
def login(request):
    if request.method == "post" or request.method == "POST":
        print(request.POST,"\n")
        print(request.POST.get("username"),request.POST.get("password"))
​
        # 实现从数据库中取出数据
        # select * from user where username=request.POST.get("username")
        # 返回值是我们的列表中的一个一个满徐条件的对象列表
        res = models.User.objects.filter(name=request.POST.get("username"))
        # user_obj = res[0]  # 活取列中的第一个对象
​
        # 先实现判断是否含有返回值
        if res:
            #含有返回值就实现基本的校验密码是否匹配
            if request.POST.get("password") == res[0].password:
                return HttpResponse("post请求的登录页面")
​
            else:
                return HttpResponse("密码错误...")
        else:
            return HttpResponse("用户不存在...")
​
    else:
        return render(request, "login.html")

Django 路由匹配

取消路由自动添加斜杠: 就要在我们的那个setting.py文件中设置:
APPEND_SLASH = False

======================================================================================
在我们实现路由匹配的时候,我们的配置就是在urls.py中实现的匹配
然后里面含有一个:
urlpatterns的配置文件
前面我们实现的是使用基本的:path来实现的路由匹配: path("路由名称", 视图函数)
但是我们的还是可以通过基本的re_path方法来实现精准的正则表达式的匹配模式: re_path(正则表达式,视图函数,name)

path('admin/', admin.site.urls),
    path("home/", views.home),
    path("about/", views.about),
    path("content/", views.content),
    path("login/", views.login),

    # 开始实现基本的re_path的使用方法
    re_path('^$', views.home)
    
=======================================================================================
当我们使用正则匹配括号的时候,那么这个时候我们就会实现基本的将其当作参数传递给函数,这个就是无名分组

re_path("test/(\d+)", view.test)

def test(request, arg):
    print(arg)
    render(request, "test.html")
    
=======================================================================================
就是我们是可以给我们的正则表达式来一个别名,基本的格式就是,这个就是我们的有名分组: (?P<别名>)
re_path("test/(?P<year>\d+)", views.test)

def test(request, year):
    print(year)
    render(request, "test.html")
    
# 注意我们的无名分组和又名分组不可以混合使用,但是可以实现的是一种正则表达式实现多次使用
re_path("test/(?P<year>\d+)/(?P<month>\d+)/(?P<date>\d+)", views.test)

def test(request, year, month, date):
    print(year, month, date)
    render(request, "test.html")

Django 反向解析

通过一些方法就可以实现得到一些结果,从而来实现触发一些函数
就是实现的是我们的路由匹配怎么实现改变,我们都可以实现访问这个函数

方法1: 就是给我们的的url取别名即可

前端页面实现的操作
<a href="{% url 'xxx' %}">1234</a>
path("func", view.func, name=xxx)

后端想要解析我们的后缀名,就是实现的reverse来实现的
首先我们需要先导入
from django.shortcuts import render, HttpResponse, redirect, reverse
print(reverse("xxx")) # 就是实现的是得到了最后的那个: func


================================================================================
有名分组和无名分组中的反向解析
re_path("test/(?P<year>\d+)/(?P<month>\d+)/(?P<date>\d+)", views.test, name=time)
<a href="{% url 'time' '1' %}"></a>
print(reverse("time", kwarg={'year':123, 'month':6, 'date':21}))

# 首先我们的time只可以用来实现匹配得到test的内容

Django 的注意事项

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',
]

# 上面的就是我们的原本的settings的代码,但是在没有设置中间件的时候,我们是需要实现基本的一些就是需要注释一条内容,post请求时候
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',
]
# 上面的注释的内容就是为了防止我们在实现post请求的时候出现基本的一些问题:就是出现需要我们传递token来确保安全
<!-- 原本的登录页面 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    {% load static %}
    <link rel="stylesheet" href="">
    <script src=""></script>
</head>
<body>
<h1>登录页面</h1>
<form action="" method="post"><!--{% csrf_token %}-->
    username(用户名):<input type="number" placeholder="请输入账号" name="username">
    password(密码):<input type="password" placeholder="请输入密码" name="password">
    <input type="submit" value="登录">
</form>
</body>
</html>
# urls.py 下的路由的配置
"""ProjectDjango URL Configuration
​
The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, re_path
from app import views
​
urlpatterns = [
    path('admin/', admin.site.urls),
    # 开始实现我们的登录功能的重写
    path('login/', views.login, name='login')
]
​
# views.py 中的业务逻辑的开发实现,我们的这里就是实现的是登录页面的实现
from django.shortcuts import render, HttpResponse, redirect
from app import models
"""
render 就是用于实现的是返回我们的html页面给前端页面
       一般的话,我们的render函数,实现的基本的语法规则就是: 一个是请求参数,一个是html页面
HttpRequest 就是用于实现返回我们的普通的字符串给我们的前端页面
redirect 就是用于实现重定向
"""
# 开始书写我们的登录功能的函数
"""
request 就是用来实现接收我们的前端返回来的数据
"""
def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 然后在我们的数据库中实现比对信息是否正确
        # filter就是用于实现过滤的
        res = models.User.objects.filter(username=username)
        if res:
            if password == res[0].password:
                return HttpResponse("登录成功")
            else:
                return HttpResponse("登录失败,密码错误...")
        else:
            return HttpResponse("登录失败,用户不存在...")
    return render(request, 'login.html')
​
# 当我们需要连接数据库的时候,我们就需要在我们的settings.py中实现设置数据库信息
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME' : 'atm',
        'USER' : 'root',
        'PASSWORD' : '451674',
        'HOST' : '127.0.0.1',
        'PORT' : '3306',
        'CHARSET': 'utf8'
    }
}
# 实现了连接数据库之后,我们再想办法实现在models.py中创建类来实现操作数据库
from django.db import models
# Create your models here.
# 首先先实现继承关系
class User(models.Model):
    # 就是一一对应的关系,就是映射
    # 就是实现的是id int primary key auto_increment
    id = models.AutoField(primary_key=True)
    # username varchar(24)
    name = models.CharField(max_length=24)
    # password varchar(24)
    password = models.CharField(max_length=24)
# 在实现创建数据库后,我们就要执行数据库的迁移

# 首先将我们的操作数据库的记录实现迁移到我们的 migrations 的目录下
python manage.py makemigrations

# 这个就是实现的是将我们的数据库实现迁移的步骤
# 但是我们在实现这一步的时候,需要先实现基本的下载第三方模块: pip install mysqlclient
python manage.py migrate

Django 的登录和注册的后端业务逻辑的实现

from django.shortcuts import render, HttpResponse, redirect
from app import models

# 下面的就是实现的是登录功能的页面的后端业务逻辑
def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 然后在我们的数据库中实现比对信息是否正确
        # filter就是用于实现过滤的
        res = models.User.objects.filter(username=username)
        if res:
            if password == res[0].password:
                return HttpResponse("登录成功")
            else:
                return HttpResponse("登录失败,密码错误...")
        else:
            return HttpResponse("登录失败,用户不存在...")
    return render(request, 'login.html')

# 开始实现注册功能的业务逻辑的实现
def register(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        re_password = request.Post.get('re_password')
        # 直接将我们的数据直接传入数据库
        if password == re_password:
            models.User.objects.create(username=username, password=password)
            return redirect('login.html')
        else:
            return HttpResponse("注册失败,两次密码不一致")
    return render(request, 'register.html')
<!-- 登录页面 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    {% load static %}
    <link rel="stylesheet" href="">
    <script src=""></script>
</head>
<body>
<h1>登录页面</h1>
<form action="" method="post"><!--{% csrf_token %}-->
    username(用户名):<input type="text" placeholder="请输入账号" name="username"><br>
    password(密码):<input type="password" placeholder="请输入密码" name="password"><br>
    <input type="submit" value="登录">
</form>
</body>
</html>


<!-- 注册页面 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>注册页面</h1>
<form action="" method="post"><!--{% csrf_token %}-->
    username(用户名):<input type="text" placeholder="请输入账号" name="username"><br>
    password(密码):<input type="password" placeholder="请输入密码" name="password"><br>
    re_password(确认密码):<input type="password" placeholder="再次输入密码" name="re_password"><br>
    <input type="submit" value="注册">
</form>
</body>
</html>

Django 实现将我们的后端的所有数据展示给页面

from django.contrib.auth.hashers import make_password, check_password
from django.shortcuts import render, HttpResponse, redirect
from app import models

# 下面的就是实现的是登录功能的页面的后端业务逻辑
def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 然后在我们的数据库中实现比对信息是否正确
        # filter就是用于实现过滤的
        res = models.User.objects.filter(username=username)
        if res:
            if check_password(password, res[0].password):
                return HttpResponse("登录成功")
            else:
                return HttpResponse("登录失败,密码错误...")
        else:
            return HttpResponse("登录失败,用户不存在...")
    return render(request, 'login.html')

# 开始实现注册功能的业务逻辑的实现
def register(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        re_password = request.POST.get('re_password')
        # 直接将我们的数据直接传入数据库
        if password == re_password:
            models.User.objects.create(username=username, password=make_password(password))
            return HttpResponse("登录成功")
        else:
            return HttpResponse("注册失败,两次密码不一致")
    return render(request, 'register.html')

"""
开始我们的基本的功能就是将我们的数据库种的每个数据实现获取出来
然后给我们的前端按钮来实现基本的增加两个按钮
一个编辑,一个删除
"""
def userList(request):
    # 开始实现获取数据库中的所有数据
    All_User_Data = models.User.objects.all()
    # local()就是用来实现返回前端页面,
    # render 可以通过我们的第三个参数来实现返回后端数据
    # 第一种情况就是实现的是: 使用字典的形式来传递部分参数: {'字段名':数据变量名称}
    # 或者实现基本的使用我们的locals函数来实现基本的传递数据,就是通过的我们的
    # 将本页面中的所有的数据组成一个个的键值对自动返回给页面
    return render(request, 'userList.html', {'All_User_Data': All_User_Data})

# 实现编辑页面的跳转
def edit(request, id):
    editId = id
    # 开始实现查询我们用户需要编辑的页面
    res = models.User.objects.filter(id=id).first()
    # 使用这个数据来实现通过前端页面实现改变
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 当我们实现修改密码后,我们就要实现我们数据库种的数据实现修改
        res.update(username=username, password=make_password(password))
        # 实现重定向用户的页面
        return redirect('/userList/')
    return render(request, "edit.html", locals())

# 实现删除页面的跳转
def delete(request, id):
    # 直接获取我们需要实现删除的用户,直接删除就可以了
    # 因为我们的查询结果可能存在多个,所以说delete可能是全部删除
    models.User.objects.filter(id=id).first().delete()
    # 然后实现重定向展示页面就可以了
    return redirect('/userList/')
<!-- 用户的界面, userList.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>开始我们的数据展示页面</h1>
<!-- 开始使用我们的表格来实现获取我们的数据 -->
<div>
    <div>
        <table>
            <!-- 表头 -->
            <thead>
                <!-- 一行内容 -->
                <tr>
                    <!-- 就是一行中的内容 -->
                    <th>id(编号)</th>
                    <th>username(用户名)</th>
                    <th>password(用户密码)</th>
                    <th>method(功能)</th>
                </tr>
            </thead>
​
            <!-- 表格主题 -->
            <tbody>
                {% for foo in All_User_Data %}
                    <tr>
                        <td>{{ foo.id }}</td>
                        <td>{{ foo.username }}</td>
                        <td>{{ foo.password }}</td>
                        <td>
                            <a href="/edit/{{ foo.id }}/">编辑</a>
                            <a href="/delete/{{ foo.id }}/">删除</a>
                        </td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>
    </div>
</div>
</body>
</html>
​
​
<!-- 用户编辑的界面, edit.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>需要实现需改的用户名的页面</h1>
<div>
    <form action="" method="post">
        <div>用户编号(id):{{ editId }}</div>
        <div>用户名(username):<input type="text" name="username" value="{{ res.username }}"></div>
        <div>密码(password):<input type="password" name="password" value="{{ res.password }}"></div>
        <div><input type="submit" value="提交修改"></div>
    </form>
</div>
</body>
</html>

Django 的路由分发

就是每一个应用的时候,我们的实现就是实现的是:含有多个app的程序
这个时候,我们的就需要含有属于自己的app和template 以及urls

由于我们的每一个文件的实现都是实现的是:组长在实现我们的合并的时候
就需要在最后整合的时候,实现最后的整合,这一步就利用到了我们的路由分发

这个时候就需要我们在app中再次创建一个urls.py的文件,来实现我们的路由的分配
创建一个新的应用的方法: python manage.py startapp app的名称

实现了这一步之后,我们就可以得到我们的app应用
最后,我们需要实现的就是完成我们在每一个app中创建一个app的urls
urls就是实现的是对应的每一个的路由匹配的功能
# projectDjango.urls
from django.contrib import admin
from django.urls import path, re_path, include
# 开始实现我们的将每个应用中的路由匹配规则全部实现倒过来,并且实现重命名
from app import urls as app_urls
from app01 import urls as app01_urls

urlpatterns = [
    path('admin/', admin.site.urls),
    # 开始实现我们的在总路由中实现路由分发,用来实现识别处于不同的文件中的路由规则
    # 总路由实现的就是实现基本的分发的处理,来实现识别我们的最后的识别来自于哪一个应用中的路由urls
    path('app/', include(app_urls)),
    path('app01/', include(app01_urls)),
    """
    同时我们还是可以实现不用导入模块直接使用的
    path('app/', include('app.urls')),
    path('app/', include('app.urls')),
    """
]



# app.urls
from django.urls import path, re_path
from app import views

urlpatterns = [
# 开始实现我们的登录功能
    path('login/', views.login),
    # 开始实现我们的注册功能的url设置
    path('register/', views.register),
    # 实现数据展示的页面
    path('userList/', views.userList),
    # 实现基础的编辑数据的页面
    re_path('edit/(\d+)/', views.edit),
    # 开始实现完善我们的删除界面
    re_path('delete/(\d+)/', views.delete)
]


# app01.urls
from django.urls import path, re_path
from app01 import views
urlpatterns = [

]


"""
同时我们还是会有基本别名空间的
就是当我们在两个不同的路由中实现了命名别名
但是两个别名一致,name
这个时候,我们就需要实现基在总路由中实现
命名空间,namespace
"""

Django 视图层

首先我们的这个函数就是实现的是,我们的py的一个一个的函数来实现的

就是每一个函数就对应每一个视图

然后在这个响应里面,我们的响应前端页面都是需要基本的一些: HttpResponse, render, redirect

视图层就是实现的是用于实现接收web请求并且返回web响应
每一个视图函数都必须是含有第一个参数request

HttpResponse, render, redirect, JsonResponse

我们的这里就需要使用到基本的json模块来实现基本的一些功能
JsonResponse 

我们再返回一个字典格式的数据的时候,我们就需要实现基本的一些功能就是: 使用我们的json模块
来实现转化我们的基本的字典数据
然后再通过我们的HttpResponse来实现返回

同时我们还是可以实现通过上面的两个步骤来实现基本的融合为一个步骤来实现
就是直接使用我们的JsonResponse直接实现传递即可
from django.http import JsonResponse
import json

# Create your views here.
# 开始实现创建我们的测试函数
def test(request):
    data_dict = {'test': '测试函数', 'data_dict': [1, 2, 3]}
    # 开始实现转换我们的数据,ensure_ascii=False 这个就是用来实现基本的防止转数据的时候出现错误
    # data_str = json.dumps(data_dict, ensure_ascii=False)
    # return HttpResponse(data_str)

    # 或者说我们还是可以直接通过我们的JsonResponse 来实现基本的一些功能的
    # safe=False 这个就是为了防止有中文乱码
    # 准确来说也是一种保护数据的一种体现
    return JsonResponse(data_dict, safe=False)

Django form表单上传文件后端如何实现获取

前端上传文件的时候,就是通过的我们的input框来实现的基本的操作的
​
然后就是我们需要考虑的就是如何实现基本的如何实现后端获取文件
​
表单上传文件的时候,我们需要实现的是两件事情:
1.method 必须指定为: post
2.enctype 换成 form-data
enctype 就是我们的 encodetype 的编码类型,默认值是我们的的 application/x-www-form-urlencoded
这个的话我们是不可以实现上传文件,只能获取的是我们的文本数据
multipart/form-data 就是允许的是我们传递的是我们的文本数据,又有文件的二进制格式的数据
​
request.FILES.get('file') 获取文件的操作
# app01.views.py
# 开始实现文件上传的业务逻辑了
def file(request):
    if request.method == 'POST':
        print(request.POST)
        # 实现获取我们的前端传递的数据
        username = request.POST.get('username')
        # 获取文件数据的方法
        file_data = request.FILES.get('file')  # 实现的是获取文件对象
        print(username, file_data.name)
​
        # 开始实现我们的读取文件的操作
        with open(file_data.name, 'wb') as f:
            for chunk in file_data.chunks():
                f.write(chunk)
    return render(request, 'file.html')
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
    username(用户名):<input type="text" name="username"><br>
    select-file(选择文件):<input type="file" name="file"><br>
    <input type="submit" value="上传文件">
</form>
</body>
</html>
# app01.urls.py
from django.urls import path, re_path
from app01 import views
urlpatterns = [
    path('test/', views.test),
    path('file/', views.file)
]
开始实现总结request的方法含有那些:

request.POST.get(键名) 获取数据列表中的最后一个数据
request.POST.getlist(键名) 获取整个列表数据
request.path 获取路径
request.path_info 获取路径
request.get_full_path() 获取路径,这个可以实现获取网页的完整的路径,包括参数

print(request.path, request.path_info, request.get_full_path())

Django 的FBV 和 CBV

FBV 就是一种基于函数的一种处理视图的方式: function basic views
CBV 就是一种基于面向对象的处理视图的方式: class basic views
就是将视图函数的逻辑拆成类下的一个一个的函数,依靠对象中的函数来实现操作我们的视图
from django.http import JsonResponse
from django.views import View
from django.shortcuts import render, HttpResponse
from django.shortcuts import render

# 先实现定义一个类,同时实现继承我们的视图
class loginView(View):
    """
    注意: 当我们看View的底层源码的时候,我们就可以了解得到:就是我们的get和post函数是我们来实现处理页面的时候必须函数
    """
    # 开始实现书写类中的函数函数来实现基本的功能,在这里的就是我们的处理get请求的方式
    def get(self, request):
        return render(request, 'login.html')

    # 开始实现我们的post请求的处理函数
    def post(self, request):
        return HttpResponse("欢迎来到post请求页面")
# 开始实现我们的处理CBV的处理对象的对象: 就是实现的自动调用loginView-> 实现了直接实例化
path('login/', views.loginView.as_view(), name='login'),

Django 模板层

通过我们的模板语法将我们的后端数据实现返回给前端页面

Django 模板层的基本语法

{{ 变量名 }} : 变量相关的处理
{%  %}: 逻辑相关的处理

模板语法是可以支持传递所有的数据类型,传递函数的时,可以自动调用函数的,但是仅仅限于无参数函数
class IndexView(View):
    def get(self, request):
        num = 123
        data = [1, 2, 3, 4, 5]

        def func():
            return 'hello world'

        class Myclass:
            def get_method(self):  # 就是对象的绑定方法
                return 'get_method'

            @classmethod
            def get_class(cls):  # 就是类实现绑定的方法
                return 'Myclass'

            @staticmethod
            def get_static():  # 就是我们的静态方法,全局都可以实现调用
                return 'static'

        myclass = Myclass()
        return render(request, 'indexNew.html', locals())

    def post(self, request):
        return HttpResponse("post请求页面")
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>整形数据:{{ num }}</p>
    <p>列表数据:{{ data }}</p>
    <p>函数数据:{{ func }}</p>
    <br>
    <p>{{ Myclass }}</p>
    <p>类中的对象绑定方法:{{ Myclass.get_method }}</p>
    <p>类中的类绑定方法:{{ Myclass.get_class }}</p>
    <p>类中的静态方法:{{ Myclass.get_static }}</p>
    <br>
    <p>{{ myclass }}</p>
    <p>实例化对象中的对象绑定方法:{{ myclass.get_method }}</p>
    <p>实例化对象中的类绑定方法:{{ myclass.get_class }}</p>
    <p>实例化对象中的静态方法:{{ myclass.get_static }}</p>
    <br/>
    <ul>
        {% for dataItem in data %}
        <li>{{ dataItem }}</li>
        {% endfor %}
    </ul>
</body>
</html>

Django 模板语法逻辑处理(过滤器)

首先我们的过滤器的话,最多包含两个参数
这个就相当于是我们的内置函数
django中含有多种过滤器,但是内置的只需要了解几个就行了

基本的语法: {{ 数据|过滤器:参数 }}

第一种:实现统计我们的字符串的长度
<p>{{ str|length }}</p>

第二种:实现默认值的操作
<p>{{ bool|default:"啥也不是" }}</p>

第三种:实现获取文件大小,本质上就是实现的将一串数字转换为文件大小的格式
<p>{{ files|filesizeformat }}</p>

第三种:实现我们的日期格式
<p>{{ current_time|date:'Y-m-d h:i:s' }}</p>
Y 表示的年, m表示的月, d表示的日, h表示的小时, i表示的是分, s表示的秒

第四种:切片操作
<p>{{ list|slice:'0:4:2' }}</p>

第五种:实现截取单词
<p>截取英文:{ eng|truncatewords:10 }}</p>
<p>截取中文:{{ china|truncatechars:10 }}</p>

第六种:移除空格
<p>移除空格:{{ eng|cut:' ' }}</p>

第七种:拼接操作
<p>{{ list|join:'%' }}</p>

第八种: 转义
后端数据为: data = '<h1>你好呀</h1>'
<p>{{ data|safe }}</p>

<!-- 注意我们实现的是通过在前端页面来对数据实现的处理,我们也是可以通过后端数据处理后再实现返回给前端是一样的 -->

Django 中的模板语法逻辑操作

1.在前端页面的for循环的操作:
{% for item in 可迭代对象 %}
	前端标签
{% endfor %}
这种模板语法常用于我们的列表的操作的实现
例子:
<ul>
	{% for dataItem in data %}
	    <li>{{ dataItem }}-{{ forloop }}</li>
    	<!-- 同时我们还是可以通过forloop来实现我们的获取每次的循环遍历的信息的 -->
    {% endfor %}
</ul>


2.在前端页面中的if判断
{% if 条件 %}
	内部代码
{% elif 条件 %}
	内部前端代码
{% else %}
	内部代码
{% endif %}

同时这两个是可以实现同时混合使用的
自己思考,我就不写了(不要问为什么,我懒,哈哈),通过的是我们的forloop来实现的
forloop.first 就是我们的第一次操作
forloop.last 就是我们的最后一次的操作

Django 自定义过滤器、标签、inclusion_tag

1.在我们的应用文件下面实现创建一个文件叫做: templatetags 的文件夹
这个里面就是实现的是存放我们的一些自定义的标签

2.在templatetags 的文件夹的下面自定义一个任意名称的 .py 文件

3.在我们的 py文件中写入固定的两句代码
  from django import template
  变量 = template.Library() # 实现实例化一个类出来
  
4.注意事项,我们的自定义过滤器的话,参数最多含有两个
# app01/templatetrgs/mytags.py
from django import template

# 通过下面的操作来实现实例化对象
register = template.Library()


# 开始实现自定义我们的模板标签,自定义是通过的我们的 inclusion_tag 来实现的

# 开始实现自定义过滤器: 注意这个是我们的python 3.5 之后添加的一个用于实现类型检查的函数写法
# 虽然这些类型提示不会改变Python的运行方式(‌因为Python是动态类型语言)‌,‌但它们可以被类型检查器和其他工具使用

@register.filter(name='get_sum')  # 通过语法糖来实现为我们的过滤器起别名
def get_sum(v1: int, v2: int):
    return v1 + v2

# 自定义标签
# 形参的意思就是: 传入一个数据,通过**来实现将我们的数组实现基本的分解成一个有一个的函数
@register.simple_tag(name='get_three_sum')
def get_three_sum(num_list: list) -> int:
    return sum(num_list)

# 最后一个就是实现的解决代码的重复来实现的,防止在多个html文件中含有多种相同的内容
# 函数,模板html页面
@register.inclusion_tag('base.html')
def left_lap(n: int):
    # 列表生成式
    data = ['第{}项'.format(i+1) for i in range(n)]
    # 第一种就是将我们的当前页面的所有的名字实现传递给页面
    return locals()
    # 第二种就是实现自定义需要传递给前端页面的数据
    # return {'data':data}
{% load mytags %}
<p>{{ num | get_sum:666 }}</p><!-- 首先我们的后面就是我们应该向我们的自定义标签传递的参数 -->
<p>{% get_three_sum data %}</p>
​
{% left_lap 6 %}}
<!-- base.html -->
<ul>
    {% for foo in data %}
        <li>{{ foo }} </li>
    {% endfor %}
</ul><!-- 注意我们的这个里面不要含有其他的代码,就只有这些,注意一哈 -->

Django 模板继承

我们实现模板继承的原因: 就是因为我们在做一些网络页面的时候,其中包含了很多的子页面
然后实现的就是实现的模板继承来实现基本的简化前端代码的书写工作
实现继承模板的方法就是:就是直接在我们的html中是按继承我们的父类模板即可
​
{% extends '模板.html' %}  这个就可以实现我们的继承模板
​
我们通过发现就可以知道,一个模板中我们需要实现修改的页面的部分
这个时候我们就要将我们需要实现修改的地方直接使用我们另一个模板语法来实现,注意我们也是需要在模板中实现这一步操作
{% block 区域名 %}
    别修改区域
{% endblock %}
​
​
一般来说的话,我们的实现的话,一般至少含有三块我们需要修改的区域: js区域,CSS区域, html区域
​
注意我们的模板继承的话,我们实现的就是基本的一些整个页面的导入
​
​
但是当我们使用到了后面的那个模板带入的话,就是使用的是我们的: {% include '模板。html' %}
通过这个我们就可以实现基本的导入局部的一些基本的样式
由于我们的前后端实现了分离,我们只用对模板层了解即可,不用做太多的了解事情

Django orm操作数据库

注意我们的那个django的内置的数据库的话是使用的是我们的sqlite
但是我们需要实现使用的是我们的mysql数据库
注意我们实现迁移数据库的时候,报错的话,应该就是我们没有第三方模块: mysqlclient
这个时候就需要我们实现下载即可
前面是有的,回头看就行了
但是操作数据之前,必须本地是具有数据库的
否则就不行,去mysql官网实现下载即可,然后像csdn搜索如何配置mysql即可

Django 操作数据库的简单操作

首先我们实现操作数据库的时候,在django中使用的是我们的是映射关系来实现的连接数据库

具体的操作数据库的话,就是通过的我们的models.py文件中实现的基本的操作
# models.py

from django.db import models

# Create your models here.
# 首先我们先创建一个类出来简介的表示我们的数据库中的表格
class UserInfo(models.Model):
    # 注意我们的基本的每一个变量就是实现的是对应的是我们的表格中的字段名
    # 用户名
    username = models.CharField(max_length=50)
    # 用户年龄
    userAge = models.IntegerField()
    # 用户密码
    password = models.CharField(max_length=50)
    # 用户邮箱
    email = models.CharField(max_length=50)
    # 注册时间,下面的时间的就是我们的年月日
    register_time = models.DateTimeField(auto_now=True)
    """
    auto_now 就是在我们每次实现操作数据的时候,那个字段会实现自动将当前的时间实现更新
    auto_now_add 就是在我们的创建的时候,就是这个时间,后面就不会随着我们的操作实现修改
    上面的两个是二选一,相互排斥的
    """

    # 在我们实现了每次的创建了一个类出来实现创建表的时候,我们就要实现基本的数据库的迁移
    # python manage.py makemigrations
    # python manage.py migrate

    def __str__(self):
        return self.username
# tests.pyfrom django.test import TestCase
# 这个里面就是实现的是我们的测试环境的搭建# Create your tests here.
# 这个里面就是用于实现的是测试我们的某一个测试文件
# 首先我们实现基本的一些准备我们的测试环境
import os
​
if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ProjectDjango.settings')
​
    import django
​
    django.setup()  # 我们实现基本的通过django来实现运行,这个就是我们的基本的测试文件
​
    
    # 所有的我们需要实现测试的代码都是必须在我们的上面的几句代码时候实现书写,才可以实现基本的测试的目的
    from app01 import models
    import datetime
​
    # 获取当前数据库中所有数据
    res = models.UserInfo.objects.all()
    print(res)
​
    # 开始实现基本的向我们额数据库中增加一个数据
    current_time = datetime.datetime.now()  # 先实现获取我们的当前的时间
​
    # 实现的创建基本的数据库中的每一个数据
    user_obj = models.UserInfo.objects.create(username='test', password='<PASSWORD>',
                                              userAge=16, email='<EMAIL>', register_time=current_time)
    print(user_obj)
​
    # 开始实现我们的获取我们的基本的存储我们的数据到数据库中
    user_obj.save()
​
    # 开始实现数据库的删除数据
    # 实现删除指定的数据
    res01 = models.UserInfo.objects.all().filter(username="test").delete()
    print(res01)
    # 实现我们的删除我们的指定的数据
    res02 = models.UserInfo.objects.filter(username='test').first()
    print(res02)
​
    # 修改数据
    models.UserInfo.objects.filter(username='test').update(userAge=20)
​
    user_obj.save()
    
    
    # 注意我们的queryset对象中还是可以实现基本的一些: .query来实现获取我们的原本的sql语句
    
"""
在我们的上面的展示中:
我们实现得到的是:
1.filter()
2.all()
3.update()
4.delete()
5.first()
​
6.values()  就是实现的获取我们的传入的字段名的数据
7.distinct()  就是实现的是数据根据字段名来去重
8.order_by()  就是传入某个字段名,实现根据字段名来排序,默认是升序排列
"""
django实现操作数据库的常用的方法:
models.表名.objects.下面的方法

all(): 就是实现的是查询数据库中的表的所有的数据
filter(): 就是实现的根据字段名来实现过滤
get(): 就是实现的是直接拿到我们的数据对象
first(): 就是实现的是获取的第一个元素
last(): 就是实现的是获取我们的最后一个元素
values(): 就是实现的获取指定的数据字段
values_list(): 就是实现的是获取我们的数据字段
distinct() 就是实现的是去重的操作
order_by(): 就是我们的排序
reverse(): 就是实现的反转
count() 就是实现的是统计当前的数据的个数
exclude() 就是实现的是将查询的数据实现取反,就是除了这个的数据实现查询出来
exist() 就是用来实现的是判断某个对象是否存在,返回bool值
result = models.UserInfo.objects

print(result.count())

print(result.filter(id=4).exists())

Django 的 orm区别于mysql的用法

大于: __gt
小于: __lt

大于等于: __gte
小于等于: __lte

在某个范围区间的用法: __in
寻找区间:__range

模糊查询:
__contains  区分大小写
__icontains  不区分大小写
from django.test import TestCase
​
# Create your tests here.
import os
​
if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ProjectDjango.settings')
​
    import django
​
    django.setup()  # 我们实现基本的通过django来实现运行,这个就是我们的基本的测试文件
​
    from app01 import models
    import datetime
​
    data = models.UserInfo.objects
​
    # 开始我们的数据库的操作
    # 开始实现查询我们年龄大于10小于20的数据
    print(data.filter(userAge__gt=10, userAge__lt=20))
​
    # 开始实现大于等于和小于等于
    print(data.filter(userAge__gte=10, userAge__lte=20))
​
    # 原本的sql语句就是: select * from 表名 字段名 in (10, 20, 30)
    print(data.filter(userAge__in=[16, 19, 20]))
​
    # 查询处于某个区间的数据,就是首位都有
    print(data.filter(userAge__range=[16, 20]))
​
    # 实现模糊查询,查询名字里面含有n的数据
    print(data.filter(username__icontains='T'))
​
    # 查询以什么开头,都是通过i来实现的是否区分大小写,有i就是不区分,否则就是区分
    print(data.filter(username__istartswith='T'))
    print(data.filter(username__iendswith='T'))
​
    # 查询注册日期
    print(data.filter(register_time__month="08"))  # 月
    print(data.filter(register_time__year="2024"))  # 年
注意事项:数据的表的创建的话,会实现我们的自动创建我们的组件

Django 的字段类型/参数/关系字段

字段类型
AutoField 自动增长的整型
IntergeField 整型类型(不可以实现存放手机号)
DecimalField 浮点型的字段,需要两个参数,第一位(max_digits)表示总共的位数,第二位(decimal_places)表示小数点后面的数字个数
​
BooleanField 布尔字段,True/False
NullBooleanField Null/True/False
​
CharField 字符串类型,必须指定参数max_length最长长度来表示最大字符数
TextField 大文本,一半超过4000字符的时候使用
​
DateField: 日期,auto_now(每次操作数据库时候,自动更新时间),auto_now_add(创建数据的时候记录的时间)【年月日】
TimeField: 日期,同时都是含有两个可选参数的,就是上面的两个【时分秒】
DateTimeField: 日期,包含了年月日时分秒,还是含有两个可选参数的
​
FileField: 就是用于实现存储文件的数据
ImageField: 就是用来保存图片的字段,确保存放的是图片
EmailField:就是我们的邮箱,用来实现的是校验是否复合我们的格式
字段参数
null 默认的是表示某个字段可以为空

unique 设置为true,就表示这个字段是唯一的

default 设置我们的默认值

db_column 表示的是表的名称,如果没有设定那么就直接设置为我们的属性名

db_index 给表中的字段添加索引

primary_key 表示的是添加主键
关系字段
ForeignKey 外键(创建一对多的关系)
参数: to: 设置关联的表格,可选
      to_filed 需要关联的字段,可选
      on_delete 当删除关联表的数据时,当前表和关联表的行为,一般的话就是给一个;models.CASCADM
                就是实现的是删除关联数据的时候,与之关联的也删除
                
OneToOneField 就是一对一,参数和我们的上面一样

ManyToManyField 多对多,自动创建第三张关系表
创建表以及表之间关系
from django.db import models

"""
开始实现创建我们的图书表
1.图书表
2.出版社
3.作者
4.作者详情

图书表和出版社之间的关系就是:一个图书表中含有多种图书,但是每种图书来袭不同的出版社,这个就是一对多的关系
图书表和作者: 一本图书含有多个作者,一个作者可以写多本图书,就是我们的多对多关系
作者和作者详情是一对一的关系
"""
# 图书表
class Book(models.Model):
    # 书的名称
    book_title = models.CharField(max_length=50)
    # 价格
    book_price = models.DecimalField(max_digits=10, decimal_places=2)
    # 出版日期
    book_publish_time = models.DateTimeField(auto_now_add=True)

    # 添加图书表和出版社之间的一对多的关系,一个出版社对应多本图书
    book_publisher = models.ForeignKey(to='Publisher',
                                       on_delete=models.CASCADE)

    # 图书和作者之间的多对多关系
    book_authors = models.ManyToManyField(to='Author')


# 出版社
class Publisher(models.Model):
    # 出版社名称
    publisher_name = models.CharField(max_length=50)
    # 出版社地址
    publisher_address = models.CharField(max_length=50)
    # 出版社投稿邮箱
    publisher_email = models.EmailField()


# 作者
class Author(models.Model):
    # 作者姓名
    author_name = models.CharField(max_length=50)
    # 作者年龄
    author_age = models.IntegerField()

    # 作者和作者详情的一对一关系
    author_detail_info = models.OneToOneField(to='AuthorDetailInfo',
                                              on_delete=models.CASCADE)


# 作者详情
class AuthorDetailInfo(models.Model):
    # 作者地址
    author_address = models.CharField(max_length=50)
    # 作者联系邮箱
    author_email = models.EmailField()
    
    
# python manage.py makemigrations
# python manage.py migrate
测试环境中实现增删改查
from django.test import TestCase
​
# Create your tests here.
import os
​
import app01
​
if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ProjectDjango.settings')
​
    import django
​
    django.setup()  # 我们实现基本的通过django来实现运行,这个就是我们的基本的测试文件
    from app01 import models
​
​
    # 实现一对多的增删改查
    # models.Publisher.objects.create(publisher_name="东方出版者", publisher_email="3137536916@qq.com",
    #                                 publisher_address="重庆市垫江县")
​
    # 开始实现增添数据的效果
    # 增加一条数据: create()
    # models.Book.objects.create(book_title="java炒粉", book_price=99.99,
    #                            book_publisher_id=1)
​
    # 虚拟对象
    # publisher_obj = models.Publisher.objects.filter(pk=2).first()
    # models.Book.objects.create(book_title="python到家第二版", book_price=99.99,
    #                            book_publisher_id=publisher_obj.id)
​
    # 开始实现删除效果: delete()
    # 注意如果将我们的publisher表中的书给删除了,那么就会导致book中的数据全无
    # 但是这个的删除达到的效果是我们的: 将id一一对应的数据实现的删除
    # models.Publisher.objects.filter(pk=1).delete()
​
    # 开始实现修改值: update()
    # models.Book.objects.filter(id=11).update(book_publisher_id=2)
    # publisher_obj = models.Publisher.objects.filter(pk=1).first()
    # models.Book.objects.filter(id=11).update(book_publisher_id=publisher_obj.id)
​
    # 查询数据就不用再那个了,在实现的时候,已经在进行查询了
​
    #==============================================================================
    # 多对多的实现增删改查,这个时候实际上就是来操作我们的第三张表来实现的
​
    # 首先先实现获取我们的书的对象
    # 获取了我们的id=9的这本书
    # book_obj = models.Book.objects.filter(pk=10).first()
    # 然后直接通过书籍对象来实现跳转我们的第三张表
    # print(book_obj.book_authors)
​
    # 开始实现向我们的第三张表实现添加数据 add(数字/对象)
    # 下面的操作就是实现的是将我们的book的id为9的书和作者id为1实现了绑定
    # 括号里面是可以实现传入多个作者id的,多对多嘛,一本书可有多个作者
    # book_obj.book_authors.add(1)
​
    # 删除数据remove(数字/对象)
    # book_obj.book_authors.remove(1)
​
    # 修改数据: 就是使用的我们的 set(可迭代对象)
    # book_obj.book_authors.set([models.Author.objects.filter(pk=1).first()])
​
    # 实现清空 clear() 就是将我们的第三张表中的绑定关系全部清空
    # book_obj.book_authors.clear()

Django 正反向概念

正方向概念: 上面的书籍表和出版社表,外键字段在书籍表中,通过书籍表来实现查询出版社信息,就是正向
反方向概念: 通过出版社查询书籍,那么就是反向
多表查询
子查询
就是基于对象的连表查询
from django.test import TestCase

# Create your tests here.
import os

import app01

if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ProjectDjango.settings')

    import django

    django.setup()  # 我们实现基本的通过django来实现运行,这个就是我们的基本的测试文件
    from app01 import models

    # 基于对象的跨表查询
    # 开始实现正向查询
    book_obj = models.Book.objects.filter(pk=9).first()
    res = book_obj.book_publisher
    print(res)
    print(res.publisher_name)
    print(res.publisher_email)
    print(res.publisher_address)

    # 多表查询的正向查询
    res01 = book_obj.book_authors.all()
    print(res01[0])

    # 作者查询作者详情
    author_obj = models.Author.objects.filter(pk=1).first()
    res02 = author_obj.author_detail_info
    print(res02.author_address)
    print(res02.author_email)
    print(res02.id)

    # 开始实现反向查询
    # 查询结果含有多个的时候,需要实现的是:对象.表名_set.all()
    
    # select * from publisher where id =
    # (select publisher_id from book where publisher_name = "东方出版者");

    # select * from publisher where id in
    # (select publisher_id from book where publisher_name = "东方出版者");
    publisher_obj = models.Publisher.objects.filter(publisher_name="东方出版者").first()
    print(publisher_obj.book_set.all())
    print(publisher_obj.publisher_address)
连表查询
就是实现的是基于上下划线的查询
from django.test import TestCase
​
# Create your tests here.
import os
​
import app01
​
if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ProjectDjango.settings')
​
    import django
​
    django.setup()  # 我们实现基本的通过django来实现运行,这个就是我们的基本的测试文件
    from app01 import models
​
    # 开始连表查询(通过的是我们的下划线来实现的操作)
    res = (models.Author.objects.filter(pk=1).
           values("author_detail_info__author_address"))
    print(res)
    
    res01 = models.Author.objects.filter(author_detail_info__pk=1).values("author_name")
    print(res01)
    
    # 可以实现使用无限双下滑线来实现无线的连表查询的
    print(models.Book.objects.filter(pk=10).values("book_authors__author_detail_info__author_email"))
聚合查询
就是使用的是我们的aggregate
聚合查询的话,通常是和我们的分组查询annoatae来实现的联合使用
其中我们的聚合查询含有:
1.count
2.sum
3.max
4.mina
5.avg
​
首先使用的时候,需要导入那个
from django.db.models import Count, Max, Min, Avg, Sum
from django.db.models import Count, Max, Min, Avg, Sum
​
# 开始来实现我们的查询某个数据的平均值
print(models.Book.objects.aggregate(Sum('book_price'),
                                        Avg('book_price'),
                                        Count('book_price')))
# 同时我们的这里还是可以实现基本的跨表查询的
# 查询每本书的作者个数
res = (models.Book.objects.annotate(author_num=Count("book_authors")).
           values("book_title", "author_num")).all()
print(res)
​
# 统计每个出版社的买的最便宜的书的价格
# 就是先实现的是对出版社实现分组,然后通过跨表来实现查询每本书的价格的最小值
res = models.Publisher.objects.annotate(min_price=Min("book__book_price")).\
    values("book__book_title", "publisher_name", "min_price")
print(res)
​
res = (models.Book.objects.annotate(num=Count("book_authors")).filter(num__gte=1).
    values("book_title", "num")).all()
print(res)
F 和 Q 查询
如果说我们实现迁移数据库后,我们还要实现的基本的添加新的字段,那么就要给一个默认值

from django.db.moodels import F,Q
F可以帮助我们查询出来每一个对应的字段的对应的值
Q查询就是可以实现的是我们的实现基本的条件查询,就是实现的是:and or not 的联合使用
如果说我们的数据的话,实现的是基本的那个filter中使用的是,来实现的连接两个的话,那么默认的就是我们的Q查询

Django 其他参数

choices 参数
针对某些可以实现完全列举的可能性的字段,我们就可以实现通过choices来实现保存我们的可选参数
# 首先我们需要的就是实现我们的先创建我们的数据库中的表
# models.py
class User(models.Model):
    user_name = models.CharField(max_length=100)
    user_age = models.IntegerField()
    # 性别
    user_gender_choices = (
        (1, "男"),
        (2, "女"),
        (3, "保密")
    )
    # choices 的使用,下面的实现还是保存的是我们的数字,需要实现考虑的就是我们的万一不在我们的这个范围内
    user_gender = models.IntegerField(choices=user_gender_choices)
    # 1.如果我们的数字存在于这个元组的范围内,那么我们的操作是什么
    # 2.如果我们的数字不存在,那么我们的操作又是怎样的

    user_email = models.EmailField(max_length=100)
    user_password = models.CharField(max_length=100)
# 开始我们的测试函数来解决上面的两个问题: test.py
from django.test import TestCase
import os
# Create your tests here.
# 开始实现准备我们的测试环境
if __name__=="__main__":
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'book_admin.settings')
    import django
    django.setup()
​
    # 下面的就是我们的测试代码
    from app01 import models
​
    user_obj = models.User.objects
​
    print(user_obj.first().user_gender)
    # 上面的就是获取的是我们的性别对应的数字
    # 如何实现我们的获取对应的性别: get_字段名_display()
    print(user_obj.first().get_user_gender_display())
​
    # 如果说我们实现获取的时候,不在我们的可选范围中的话,那么就是我们的空,但是不会报错
# 开始实现我们的创建用户的表
class User(models.Model):
    user_name = models.CharField(max_length=100)
    user_age = models.IntegerField()
    # 性别
    user_gender_choices = (
        (1, "男"),
        (2, "女"),
        (3, "保密")
    )
    # choices 的使用,下面的实现还是保存的是我们的数字,需要实现考虑的就是我们的万一不在我们的这个范围内
    user_gender = models.IntegerField(choices=user_gender_choices)
    # 1.如果我们的数字存在于这个元组的范围内,那么我们的操作是什么
    # 2.如果我们的数字不存在,那么我们的操作又是怎样的
​
    score = (
        ("A", "优秀"),
        ("B", "良好"),
        ("C", "挺不错")
    )
    user_score = models.CharField(choices=score, max_length=10, default=1)
​
    user_email = models.EmailField(max_length=100)
    user_password = models.CharField(max_length=100)
多对多三种创建方式
1.就是使用我们的orm来实现自动的创建第三张表: 就是直接通过我们的ManyToManyField 来实现的:建议使用就是这个,方便简洁2.就是实现的是纯手动的创建我们的第三张表: 就是通过的是我们的ForeignKey来实现的
​
3.就是实现的是我们的半自动来实现的,就是一半的是自动,一半的是我们的手动
​
了解即可,代码就不来了

Django框架进阶

Django Ajax

首先我们在学习的前端时候,里面也是有一个Ajax的,这个时候,就体现了一句话Ajax是属于每种编程语言中的技术的
​
Ajax 就是实现的是: 发起异步请求,然后提交,实现最后的局部刷新
​
在我们的前面实现的是我们的前端通过input的提交按钮来实现向后端发送请求,然后后端实现处理数据,同时最后实现刷新整个页面
​
但是使用我们的ajax的时候,就是实现的向我们的后端实现请求,然后最后实现的是局部刷新
​
动态的获取用户实时的数据,然后和后端的数据实现校验,实现实时的展示给前端

前端向后端发送请求方法

1.浏览器的地址栏中直接输入我们的url,然后就可以实现发送请求,是我们的get请求
​
2.通过a标签来实现发发送请求,get请求
​
3.form表单来实现我们的提交请求: 默认的是我们的get请求,但是可以通过我们的method来实现我们的发送:post请求
​
4.通过ajax技术来实现的请求: get / post 
​
Ajax: 在不刷新整个页面的情况下来实现的是和服务器交换数据,然后进行局部的刷新
​
通过我们的ajax的请求的时候,还是可以实现的就是我们的以键值对的形式来让我们的后端实现修改数据
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    {% load static %}
    <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
    <script src="{% static 'jquery_3.6.0.js' %}"></script>
    <!--注意我们的jquery的引入一定要在这个的前面-->
    <script src="{% static 'js/bootstrap.min.js' %}"></script>
</head>
<body>
    <input type="text" id="i1">
    <br>
    <input type="text" id="i2">
    <br>
    <button id="btn">获取总和</button>
    <input type="text" id="i3">
​
    <script>
        // 我们在使用那个jQuery的时候,可以直接使用 $ 来实现替代jQuery
        jQuery("#btn").click(function() {
            console.log("我执行了")
            // 开始实现我们的ajax
            $.ajax({
                // 指定向那个地址发送请求
                url:"", // 就是默认的向我们的当前的请求地址实现提交
                // 请求方式的实现。默认的就是我们的get请求
                type:'post',
                // 发送请求的数据
                data:{'inputData01':$('#i1').val(), 'inputData02':$('#i2').val()},
                // 回调函数:就是当我们的后端返回数据结果的时候自动触发函数执行
                success: function (args) {
                    // args就是实现的我们的接收后端的返回结果
                    $('#i3').val(args)
                }
            })
        })
    </script>
</body>
</html>
from django.shortcuts import render, HttpResponse, redirect
​
# Create your views here.# 开始实现我们的创建第一个视图函数
def test(request) -> HttpResponse:
    # 开始实现接收我们的前端数据
    if request.method == 'POST':
        inputData01 = request.POST.get('inputData01')
        inputData02 = request.POST.get('inputData02')
        print(inputData01, inputData02)
​
        inputData03 = int(inputData01) + int(inputData02)
        return HttpResponse(inputData03)
    return render(request, "test.html", locals())
在我们的后端的中实现是那个: HttpResponse 实现的返回的数据,那么就不会自动的反序列化
                        JsonResponse 返回的数据,回调函数就会自动反序列化

前后端传输数据的编码格式(contentType)

这个的编码格式的话,一般我们实现考虑就是考虑的就是我们的post请求

可以向后端提交post请求的方法: form表单, ajax请求

1.urlencoded: 就是用来实现的是传输文本格式

2.formdata: 就是实现的是传输我们的文件格式

3.json: 就是实现的是用来实现传输json数据
form 默认的传输的数据格式就是我们的: urlencoded,这个就是我们的文本格式
数据格式就是我们的: username=xxx&age=10form-data的数据格式的话,就不可以通过我们的network直接看到我们的数据,这种模式的话,是专门针对于我们的文件格式来实现的
只可以通过我们的request.FILES来实现我们的接收数据
​
我们的form表单是不可以实现传输json格式的数据的
​
https://blog.csdn.net/daobuxinzi/article/details/113782211

ajax的数据格式

默认的编码格式为: urlencoded,后端实现的是通过我们的:request.POST来实现的请求发送json格式的数据: 
实现传递的时候,需要的是那个:使用我们的contentType:application/json
同时实现使用我们的JSON,stringify({})
在后端实现的时候,就是实现的是使用我们的:request,body来实现我们的那个: 获取我们的数据,默认传递的是我们的二进制的值,然后实现使用我们的那个:json.loads来实现反序列化发送文件格式的数据的时候的操作:
js的内置对象:FormData 来实现我们的处理数据
let formDataObj = new FormData()
// 实现是先放入我们的键值对
formDataObj.append(“username”, $("#elementID"))
contentType:false, // 就是实现的是不需要任何的编码
processData:false // 就是实现的是让浏览器不要对数据实现处理
后端实现的获取的方法是: request.FILES 来实现我们的接收数据
form: enctype:"multipart/form-data"这个时候我们的django可以实现的就是我们的将我们的: 对应的数据存放于对应的方法中:request.POST 和 request.FILES中

Django 后端分页的操作

分页的就是实现的是我们的那个: 每个页面中实现只展示固定个数的数据,并不是将所有的数据全部实现展示在我们的那个一个页面中
​
基本的思路就是实现的是我们的切片的操作
​
在实现我们的分页的操作的时候,我们的参数含有: 访问哪一个页面, 一页中含有多少数据, 开始实现展示的位置和结束位置
def pages_data(request):
    book_list - models.Book.objects.all()
    # 开始实现我们的获取数据的总条数
    all_count = book_list.count()
​
    # 首先我们先实现获取得到最终的get请求得到的数据
    try:
        current_page = int(request.GET.get('page'))
    except ValueError: # 如果获取不到那个page,那么就直接设置pages的初始值为1
        current_page = 1
​
    current_user = request.GET.get('user')
    # 每一页实现的是展示的条数
    per_page_num = 10
    # 每个页面的需要展示的起始位置: (页码数 - 1) * 每一页展示的数据个数
    start_num = (current_page - 1) * per_page_num
    # 每一页的结束位置: 页码数 * 每一页的数据条数
    end_num = current_page * per_page_num
​
    # 实现算出我们的具体的需要进行展示的条数,得到了商和余数
    page_num, more = divmod(all_count, per_page_num)
​
    if more:
        # 这个就是我们的最终需要实现展示的条数
        page_num += 1
​
    # 就是的是使用我们的切片操作
    show_data = models.Book.objects.all()[start_num:end_num]
​
    clone_current_page = current_page
    if clone_current_page < 6:
        current_page = 6
​
    # 如果前端不是通过的ajax来实现的我们的数据的请求,那么这个时候,我们是可以直接通过最终的拼接字符串返回给前端的
    # 直接让我们的前端实现处理数据即可
    for i in range(current_page - 5, current_page + 6):
        if clone_current_page == i:
            page_html = '<li class="blue"><a href="?page=%s">%s</a></li>' % (i, i)
        else:
            page_html = '<li><a href="?page=%s">%s</a></li>' % (i, i)
    return render(request, "page.html", locals())

Django form组件

登录原生代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 实现的是加载我们的静态资源文件 -->
    {% load static %}
    <!-- 开始实现引入我们的静态资源文件 -->
    <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
    <script src="{% static 'jquery_3.6.0.js' %}"></script>
    <script src="{% static 'js/bootstrap.min.js' %}"></script>
</head>
<body>
    <div style=>
        <!-- 开始实现书写我们的登录页面 -->
        <form action="" method="post" enctype="application/x-www-form-urlencoded">
            <p>
                <input type="text" placeholder="请输入用户名" name="username"><br>
                <!-- 开始实现展示我们的报错信息 -->
                <span style="color:red">{{ back_error_info.username }}</span>
            </p>
            <p>
                <input type="text" placeholder="请输入密码" name="password"><br>
                <span style="color:red">{{ back_error_info.password }}</span>
            </p>
            <input type="submit" value="登录">
        </form>
    </div>
</body>
</html>
from django.shortcuts import render, HttpResponse, redirect
​
# Create your views here.
# 开始实现我们的定义登录页面的视图函数
def login_view(request):
    # 开始实现拼接一个用来返回我们的错误的信息的字典
    # post请求的时候是没有报错信息的,但是只要一有错误就直接添加报错进行我们的校验
    back_error_info = {"username": "", "password": ""}
    # 开始实现获取前端数据
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 开始我们的密码的校验
        if username:
            if '666' in username:
                back_error_info["username"] = "用户名设置不正确,请重新设置"
        else:
            back_error_info["username"] = "用户名未输入"
        if password:
            if len(password) < 8:
                back_error_info["password"] = "密码少于8位,请重新设置"
        else:
            back_error_info["password"] = "用户密码未输入"
​
        # 如果登录成功,那么就是直接重定向到首页,否则就停止在这个页面
    # 直接返回一个前端页面,并且实现我们的返回当前页面的数据
    return render(request, "login_view.html", locals())

django 的内置form组件

# 开始使用我们的django内置的forms组件
class MyForm(forms.Form):
    # 开始书写我们的在前端需要生成的框
​
    # 就是表示的是我们的前端页面中的数据的是最小三位,最大六位
    username = forms.CharField(min_length=1, max_length=10)
​
    # 开始实现生成我们的密码的限制
    password = forms.CharField(min_length=8, max_length=15)
​
    # 开始我们的邮箱格式的设置
    email = forms.EmailField()
# 开始测试代码
import os
import django
from django.test import TestCase
​
# Create your tests here.
if __name__ == "__main__":
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_pro.settings')
    django.setup()
​
    # 开始实现我们的测试函数的书写
​
    # 开始实现测试我们的自定义表单的使用
    from LoginPage import views
​
    # 开始我们的校验数据
    form_obj = views.MyForm(
        {
            "username": "test",
            "password": "ndsj",
            "email": "123"
    })
    print(form_obj.is_valid())
​
    # 开始实现我们的没有通过校验的数据
    print(form_obj.errors)
    # 查看我们的通过检验的数据
    print(form_obj.cleaned_data)

实现渲染

只用用来实现渲染我们的用于实现输入的input框,不可以实现渲染我们的提交按钮
​
我们的实现渲染的话,就可以在最后的自定义的开始渲染
​
使用我们的内置的表单组件的时候,实现的时候分为三个步骤: 就是实现的是我们的: 
​
1.生成我们的表单类
2.开始在前端页面实现渲染
3.实现展示报错信息
<!-- 用于实现我们的渲input框和渲染报错信息 -->
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<!--novalidate 这个就是实现的是阻止我们的浏览器的渲染的-->
<form action="" method="post" novalidate>
    <!--开始实现我们的渲染自定义form组件-->
    <!--我们实现渲染的时候,渲染的格式含有:
    as_p 就是以我们的p标签的形式实现渲染
    as_ul 就是以我们的ul标签的形式实现渲染页面
    as_table 就是以我们的table的形式实现的是我们的全段页面的渲染
    -->
<!--    <p>第一种方式的渲染</p>-->
<!--    &lt;!&ndash; 代码的书写少,但是最终的那个可变性低 &ndash;&gt;-->
<!--    {{ form_obj.as_p }}-->
<!--    {{ form_obj.as_ul }}-->
<!--    {{ form_obj.as_table }}--><!--    <p>第二种渲染方式</p>-->
<!--    &lt;!&ndash; 就是通过我们的一个一个来实现的渲染 &ndash;&gt;-->
<!--    {{ form_obj.username.label }}:{{ form_obj.username }}-->
<!--    {{ form_obj.password.label }}:{{ form_obj.password }}-->
<!--    {{ form_obj.email.label }}:{{ form_obj.email }}-->
​
    <p>第三种的渲染方法</p>
    {% for item in form_obj %}
        <p>{{ item.label }}:{{ item }}</p>
        <!-- 开始实现展示报错信息-->
        <span style="color: red">{{ item.errors.0 }}</span>
    {% endfor %}
    <input type="submit" value="提交"></form>
</body>
</html>
# 用于实现的是我们的生成自定义表单# 开始使用我们的django内置的forms组件
class MyForm(forms.Form):
    # 开始书写我们的在前端需要生成的框
​
    # 就是表示的是我们的前端页面中的数据的是最小三位,最大六位
    # 我们还是可以自定义报错信息的,就是通过我们的error_massage 来实现的自定义报错信息
    # 我们就可以实现添加的就是: error_message={ 'min_length': "", 'max_length':'', 'required':'用户名不可为空' }
    username = forms.CharField(min_length=1, max_length=10, label="用户名")
​
    # 开始实现生成我们的密码的限制
    password = forms.CharField(min_length=8, max_length=15, label="密码")
​
    # 开始我们的邮箱格式的设置:校验邮箱格式的为: invalid
    email = forms.EmailField(label="邮箱")
​
def index(request):
    # 开始产生一个空对象
    form_obj = MyForm()
​
    # 开始实现获取我们的用户信息来实现检验
    if request.method == "POST":
        # 开始实现我们的校验逻辑的书写
        # 实现通过我们的字典来实现我们的数据的校验
        # 直接将我们的request.POST 来实现我们的页面的校验
        form_obj = MyForm(request.POST)
        # 成功的校验
        if (form_obj.is_valid()):
            return HttpResponse("登录成功")
        # 失败的校验
        else:
            # 开始实现获取我们的报错信息
            pass
​
​
    # 然后将我们的这个表单实现传递给我们的前端页面
    return render(request, 'index.html', locals())
这些的话实际上不管用,好好的实现我们的那个ajax请求就可以了,不用使用我们的这些模板语法的,了解即可,用的不多的
​
玩玩就行了

Django session和cookie

cookie + session

我们的http请求的话原本就是一个无状态的,就是实现的是将我们的用户名和密码通过cookie来实现保存起来
​
就是我们的服务器实现的是服务器将我们的用户信息实现保存,然后用户在下次实现访问这个页面的时候就可以是自动的登录
​
cookie 就是是是实现的是通过服务器发送出来是实现存储在浏览器中的一些键值对,下一次是实现基本的访问相同的页面的时候,我们就可以直接
​
免登录,就是用来保存我们的用户的个人信息的
session 就是实现的就是我们的最终的数据保存在服务端,同时他的保存形式是键值对实现的保存
从总的概述来说,我们的cookie 就是实现的是我们的保存在浏览器端的信息
然后我们的session就是实现的是我们的保存在服务端的信息
然后在我们的服务端的实现的那个保存cookie就是通过的是我们的最终的那个;
在视图函数中是实现的返回值的设置
就是通过的我们的最终的那个: return obj 来实现的返回
这个obj 的话就是是实现的是最基本的那个: 创建的HttResponse对象来实现的操作
通过的我们的最终的obj来实现的操作cookie

设置/获取cookie

就是通过的是我们的: set_cookie(key, value) 来实现的我们的操作cookie
​
获取cookie: 就是通过的是我们的request.COOKIES.get('key')来实现的获取cookie值
登录和登出的业务逻辑
# 开始实现喔们的通过登录页面来实现基本的获取cookie的值
def login(request):
    if request.method == "POST":
        # 开始实现获取我们的前端传输的信息
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username and password:
            # 下面的操作就是实现的是我们的那个用来实现我们的登录后实现的跳转是我们的最开始的那个页
            # 开始实现我们的用户上一次的访问页面url
            url = request.Get.get('next')
            if url:
                # 开始实现我们的让浏览器来实现记录我们的cookie的数据
                obj = redirect(url)
            else:
                obj = redirect('home')
                
            # 开始实现我们的设置我们的cookie的维持时间
            # max_age 就是实现的时设置我们的这个网页的cookie的超时时间
            obj.set_cookie('username', username, 'password', password, max_age=3600)    
            # 直接重定向我们的主页中去
            return obj
​
# 开始实现书写我们的登录验证的函数来实现我们的装饰器
def login_auth(func):
    def inner(request, *args, **kwargs):
        url = request.get_full_path()
        if request.COOKIES.get('username') and request.COOKIES.get('password'):
            return func(request, *args, **kwargs)
        else:
            return redirect('login/?next=%s/' % url)
    return inner
​
​
# 直接实现使用我们的装饰器来实现我们的判断是否处于登录
# 装饰器的话一般来说都是一个闭包函数
@login_auth
def home(request):
    # 开始实现我们的获取前端的cookie值
    return HttpResponse("已有cookie,欢迎来到首页界面")
​
# 开始实现我们的登出的业务逻辑的书写
@login_auth
def logout(request):
    # 开始书写我们的注销后的业务逻辑
    # 在注销后就是直接跳转到我们的登陆页面
    obj = redirect('login/?next=%s/' % request.path)
    # 开始实现我们的删除cookie的值
    obj.delete_cookie('username')
    return obj

session 的操作

当用户实现登陆后,服务器产生一个随机字符串,交给浏览器来实现保存
实现获取我们的session的方法就是:
request.session.get("key")
django对session操作的本质
设置session: 
1.django 就是实现的是我们的随机生成一个随机字符串
2.然后实现的就是将我们的这个随机字符串存储于我们的django_session的表中
3.最后实现的是返回这个生成的随机字符串返回给客户端浏览器实现保存
request.session[key] = value
​
​
获取session:
1.自动的从浏览器请求中获取sessionid对应的字符串
2.然后实现的就是实现的是拿着这个sessionid的的字符串来实现基本的从表中实现查找对应的数据
3.和数据库实现了匹配成功,那么这个时候就直接返回数据,否则就是None
request.session.get(key)
​
​
我们的django的中的session表中的数据条数只会有一条数据(相同的一台电脑和浏览器)
同台电脑和不同浏览器的时候,那么有几个浏览器实现了访问,我们的最终的呈现的效果就是:和浏览器个数一致
​
​
django的默认的session过期时间是:14天
同时我们是可以实现通过函数来设置我们的过期时间的
request.session.set_expiry()
括号中的参数设置:整数(s)
日期对象:指定过期日期
0:就是一旦关闭浏览器就失效
没得: 就是默认的django设置的时间:14天
​
​
清除session的数据
request.session.delete() 就是实现的将服务端的数据全部删除完
request.session.flush() 这个就是实现的是将服务端和客户端的数据实现全部删除

Django 中间件

请求来的时候,需要我们经过中间件,我们才可以达到django的后端服务器
​
响应走的时候,我们也是需要经过中间件才可以实现发送出去
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',
]
​
# 上面的代码就是实现的是使用我们的中间件,一共含有七个中间件,但是一般来说的话,我们在含有form表单的时候,需要将第四行注释
# 不删除的时候,也是含有解决方法的

Django 自定义中间件

我们django的自定义中间件含有五个,但是比较重要就只有两个:两个必须掌握:
process_request
process_response
​
​
三个了解:
process_view
process_template_response
process_exception
自定义中间件的方法:
1.首先先在我们的项目名中开始自定义文件夹
2.然后实现我们的自定义一个py文件(但是我们必须继承: MiddlewareMixin)
3.然后在这个类中书写这五个方法,需要书写那些就写那些
4.最后就实现的是添加到上面的中间件的配置文件中
# 首先先实现导入我们的需要继承的模块名
from django.utils.deprecation import MiddlewareMixin
​
​
# 开始实现自定义一个类,来实现书写我们的自定义的中间件方法
class MyMiddleware(MiddlewareMixin):
    # 开始实现书写我们的自定义中间件函数
​
    # 1.process_request的函数,用于实现的是接收我们的浏览器传递过来的请求函数方法
    def process_request(self, request):
        print("这个是我们在中间件中实现的定义的第一个必要的process_request函数方法")
        return request
​
    # 2.process_response的函数,这个函数就是实现的是用于返回我们的响应数据
    # 这个形参response 就是实现的是用来接收我们的视图函数返回的内容,同时这个也是可以是我们的自定内容
    # 那么我们后面实现的就是我们的这个自定义内容
    # 顺序的话就是我们的视图函数的从下向上的操作
    def process_response(self, request, response):
        print("这个是我们在中间件中需要自定义的第二个必要的process_response函数方法")
        return response
​
    # 3.就是用来实现的是我们的处理我们的视图函数的方法process_view
    # callback 就是实现的是我们的来实现我们的接收视图函数
    # 后面的两个参数就是用来实现的是接收我们的视图函数的接收的参数
    # 这个方法就是实现的是在我们的路由匹配成功后,可以实现自动执行的中间件中的方法
    # 顺序也是我们的怕配置文件的从下往上的顺序来实现的运行
    def process_view(self, request, callback, callback_args, callback_kwargs):
        print(request)
        print(callback)
        print(callback_args)
        print(callback_kwargs)
        return callback(request, callback_args, callback_kwargs)
​
    # 4.这个函数就是实现的是我们的最终的在响应成功之后执行的函数
    def process_template_response(self, request, response):
        print(request)
        print(response)
        return response
​
    # 5.就是实现的是我们的异常处理,就是在我们的执行函数中出现异常的时候使用的函数
    def process_exception(self, request, exception):
        print(request)
        print(exception)
        return request
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',
    'LoginPage.mymiddleware.mymiddlerware.MyMiddleware',
]

Django 的中间件配置项第四句话讲解

'django.middleware.csrf.CsrfViewMiddleware'
​
我们的这句话就是来实现的是开实现检查我们的所有的状态是否合法,来检查我们的请求和响应是否合法
针对于我们的form表单的

csrf跨站请求伪造

就是我们的钓鱼网站,就是一个和我们的原本的正规网站是分相似的网站,就是一个一比一还原的盗版网站
​
在这个的背景之下,我们就出现了对这个csrf的需求
​
我们为了解决这个问题,我们就要通过给我们的页面加上一个唯一标识来实现防止csrf伪造
​
只有我们的标识符匹配,才可以实现发送请求
​
就是直接在form表单中添加 {% csrf_token %}

Django中的auth模块的使用

首先现在开始实现我们的获取微信/qq/邮箱来实现发送消息的函数的实现
def wechat(content):
    print("微信通知", content)
​
def Qq(content):
    print("QQ通知", content)
​
​
 def Email(content):
    print("邮箱通知", content)
import webbrowser
​
from relative import *
​
# 开始实现我们的传输我们的信息
def send_all(content):
    wechat(content)
    Qq(content)
    Email(content)
​
send_all("hello world")
上面的就是我们的基本的思路的实现,就是先实现定义,然后实现我们的在另一个模板中使用我们的定义的方法即可
# qq.py
class NotifyQQ:
    def __init__(self):
        pass
​
    def send_msg(self, msg):
        print("QQ通知", msg)
# wechat.py
class NotifyWeChat:
    def __init__(self):
        pass
​
    def send_msg(self, msg):
        print("微信通知", msg)
# email.py
class NotifyEmail:
    def __init__(self):
        pass
​
    def send_msg(self, msg):
        print("邮箱通知", msg)
# setting.py
NoTIFY_LIST = [
    "notify.qq.NotifyQQ",
    "notify.wechat.NotifyWeChat",
    "notify.email.NotifyEmail",
]
# test.py
# 开始实现我们的执行文件的书写
# from notify import qq, wechat, email# 开始实现我们的调用函数
# qq = qq.NotifyQQ()
# wechat = wechat.NotifyWeChat()
# email = email.NotifyEmail()
#
# qq.send_msg("hello")
# wechat.send_msg("hello")
# email.send_msg("hello")
​
from django.shortcuts import settings
import importlib
​
# 开始实现我们的发送我们的信息
def send_all(content):
    # 先实现我们的循环遍历
    for item in settings.NOTIFY_LIST:
        # 然后就开始实现我们的额切分字符串来实现切分为左右两个部分
        # 第一个是我们的模块的路径,第二个是我们的模块的类名
        module_path, class_name = item.rsplit(".", maxsplit=1)
        # 这个就是实现是我们的拿到我们的导入我们需要实现使用的模块
        module = importlib.import_module(module_path)
​
        # 开始实现使用我们的getattr来实现获取我们的类名, getattr(路径, 类名) --》获取类名
        cls = getattr(module, class_name)
        obj = cls()
        obj.send(content)

auth模块的开始使用

auth 创建超级管理员
就是我们在实现创建一个项目的时候,我们可以发现,会默认含有一个admin的视图函数,这个就是我们的超级管理员的视图函数
​
python manage.py createsuperuser
​
我们实现通过这个指令可以实现的是我们的创建我们的超级用户
然后就可以实现使用我们的admin的路由的页面了
​
我们的管理员默认的就是我们的管理我们的auth_users的表中的数据,admin就是实现的是我们的来管理我们的数据的
我们同时是可以来实现添加我们的管理员可以实现的操作的数据,否则默认的就只有我们的auth_users表中的数据
from django.contrib import admin
from django.contrib import auth
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
​
# Register your models here.
# 开始实现我们的添加我们的管理员可以实现管理的数据,否则就是我们的最基本的那个:auth_users# 开始实现书写我们的管理员的登录页面
def Manager_login(request):
    if request.method == 'POST':
        # 开始实现我们用户的登录的用户名以及密码
        username = request.POST['username']
        password = request.POST['password']
        # 在我们的用户表中实现来校验我们的用户是否存在
        # 然后实现我们的密码实现比对
        # 开始实现我们的校验
        # authenticate: 可以做的事情含有两个,一个就是自动查询我们的auth_user表,一个就是自动给密码实现加密
        # 然后实现的就是返回我们的用户对象
        res = auth.authenticate(request, username=username, password=password)
​
        if res:
            # 开始实现我们的保存用户的登录的状态
            # 只要实现了我们的这个方法,我们就可以实现在任何地方来获取 request.user获取登录的用户对象
            auth.login(request, res)
​
    return render(request, 'admin/login.html')
​
​
# 我们是可以实现的是我们的在全局中实现使用我们的LOGIN_URL 来配置我们的默认的跳转路径
@login_required(login_url='admin:login')
def home(request):
    # 用来实现的是判断我们的用户是否处于登录状态,返回的是我们的bool类型
    print(request.user.is_authenticated)
我们实现登录的时候,我们需要实现的是我们的对密码和用户名的校验
​
原本的就是在我们的数据库表中的一些具体的操作来实现的获取我们的密码和用户名来实现校验
​
auth.authenticate(request, username, password) 来实现将我们的信息和数据库中的用户来实现查找数据库中的详细信息
​
auth.login(request, 用户) 用来实现的是保存我们的用户登录的状态
​
request.user 实现的是查询我们的已经登录的用户有哪些
​
request.user.is_authenticated 来实现的是我们的判断用户是否处于登录的状态
​
from django.contrib.auth.decorators import login_required
@login_required(login_url=“跳转地址”) 来实现我们的最后的判断用户是否处于登录的装饰器,被装饰的部分只有用户处于登录的情况下才可以实现使用
​
同时这个登录的校验我们还是可以实现的是进行全局配置的: 就是在我们的setting.py中实现使用我们的: LOGIN_URL="路径"
​
​
https://blog.csdn.net/achen_m/article/details/134631126

auth 实现修改密码逻辑

from django.contrib import admin
from django.contrib import auth
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
​
# Register your models here.
# 开始实现我们的添加我们的管理员可以实现管理的数据,否则就是我们的最基本的那个:auth_users# 开始实现书写我们的管理员的登录页面
def Manager_login(request):
    if request.method == 'POST':
        # 开始实现我们用户的登录的用户名以及密码
        username = request.POST['username']
        password = request.POST['password']
        # 在我们的用户表中实现来校验我们的用户是否存在
        # 然后实现我们的密码实现比对
        # 开始实现我们的校验
        # authenticate: 可以做的事情含有两个,一个就是自动查询我们的auth_user表,一个就是自动给密码实现加密
        # 然后实现的就是返回我们的用户对象
        res = auth.authenticate(request, username=username, password=password)
​
        if res:
            # 开始实现获取我们的url
            url = request.GET.get('url')
            # 然后对我们的url来实现操作
            if url:
                return redirect(url)
            # 开始实现我们的保存用户的登录的状态
            # 只要实现了我们的这个方法,我们就可以实现在任何地方来获取 request.user获取登录的用户对象
            auth.login(request, res)
​
    return render(request, 'admin/login.html')
​
​
# 我们是可以实现的是我们的在全局中实现使用我们的LOGIN_URL 来配置我们的默认的跳转路径
@login_required(login_url='admin:login')
def home(request):
    # 用来实现的是判断我们的用户是否处于登录状态,返回的是我们的bool类型
    print(request.user.is_authenticated)
​
​
# 开始实现我们的修改密码的功能的完善
# 我们在实现我们的修改密码的时候,需要实现还是我们的先确保用户处于一个登录状态否则跳转登录
@login_required(login_url='admin:login')
def set_password(request):
    if request.method == 'POST':
        # 开始实现我们的获取前端页面传入的数据: 新密码 + 旧密码 + 确认密码
        old_password = request.POST.get('old_password')
        new_password = request.POST.get('new_password')
        confirm_password = request.POST.get('confirm_password')
​
        # 先实现我们的校验两次密码是否输入一致
        if new_password == confirm_password:
            # 然后实现我们的校验旧密码是否一致
            # check_password 实现的是将我们的传入的密码实现加密后和数据库中的密码进行校验,返回bool值
            if request.user.check_password(old_password):
                # 通过校验后,直接修改密码,同时实现加密
                request.user.set_password(new_password)
                # 最后实现的就是我们的调用数据库,然后保存数据
                request.user.save()
        # 修改密码成功后,就重定向我们的登录页面
        return redirect("/login/")
    return render(request, 'set_password.html', locals())

auth来实现登出功能

# 首先我们需要实现的还是我们的先判断我们的用户是否处于一个登录的状态,否则就要跳转到我们的登录页面
@login_required(login_url='admin:login')
# 开始实现完善我们的额逻辑
def logout(request):
    # 直接实现的是:到达我们的session表中将我们的数据进行删除
    auth.logout(request)
​
    # 将session表中的数据删除后直接重定向即可
    return redirect("/login/")

auth 注册功能实现

from django.contrib import admin
from django.contrib import auth
from django.contrib.auth.models import User
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
​
# Register your models here.
# 开始实现我们的添加我们的管理员可以实现管理的数据,否则就是我们的最基本的那个:auth_users# 开始实现书写我们的管理员的登录页面
def Manager_login(request):
    if request.method == 'POST':
        # 开始实现我们用户的登录的用户名以及密码
        username = request.POST['username']
        password = request.POST['password']
        # 在我们的用户表中实现来校验我们的用户是否存在
        # 然后实现我们的密码实现比对
        # 开始实现我们的校验
        # authenticate: 可以做的事情含有两个,一个就是自动查询我们的auth_user表,一个就是自动给密码实现加密
        # 然后实现的就是返回我们的用户对象
        res = auth.authenticate(request, username=username, password=password)
​
        if res:
            # 开始实现获取我们的url
            url = request.GET.get('url')
            # 然后对我们的url来实现操作
            if url:
                return redirect(url)
            # 开始实现我们的保存用户的登录的状态
            # 只要实现了我们的这个方法,我们就可以实现在任何地方来获取 request.user获取登录的用户对象
            auth.login(request, res)
​
    return render(request, 'admin/login.html')
​
​
# 我们是可以实现的是我们的在全局中实现使用我们的LOGIN_URL 来配置我们的默认的跳转路径
@login_required(login_url='admin:login')
def home(request):
    # 用来实现的是判断我们的用户是否处于登录状态,返回的是我们的bool类型
    print(request.user.is_authenticated)
​
​
# 开始实现我们的修改密码的功能的完善
# 我们在实现我们的修改密码的时候,需要实现还是我们的先确保用户处于一个登录状态否则跳转登录
@login_required(login_url='admin:login')
def set_password(request):
    if request.method == 'POST':
        # 开始实现我们的获取前端页面传入的数据: 新密码 + 旧密码 + 确认密码
        old_password = request.POST.get('old_password')
        new_password = request.POST.get('new_password')
        confirm_password = request.POST.get('confirm_password')
​
        # 先实现我们的校验两次密码是否输入一致
        if new_password == confirm_password:
            # 然后实现我们的校验旧密码是否一致
            # check_password 实现的是将我们的传入的密码实现加密后和数据库中的密码进行校验,返回bool值
            if request.user.check_password(old_password):
                # 通过校验后,直接修改密码,同时实现加密
                request.user.set_password(new_password)
                # 最后实现的就是我们的调用数据库,然后保存数据
                request.user.save()
        # 修改密码成功后,就重定向我们的登录页面
        return redirect("/login/")
    return render(request, 'set_password.html', locals())
​
​
​
# 首先我们需要实现的还是我们的先判断我们的用户是否处于一个登录的状态,否则就要跳转到我们的登录页面
@login_required(login_url='admin:login')
# 开始实现完善我们的额逻辑
def logout(request):
    # 直接实现的是:到达我们的session表中将我们的数据进行删除
    auth.logout(request)
​
    # 将session表中的数据删除后直接重定向即可
    return redirect("/login/")
​
​
# 开始实现我们的注册功能
def Manage_register(request):
    # 实现我们的注册功能的话,我们需要是实现的是我们的经密码和用户名存储如数据库
    if request.method == 'POST':
        # 开始实现我们获取我们前端传入的数据
        username = request.POST.get('username')
        password = request.POST.get('password')
​
        # 开始实现我们的存储数据于数据库中
        # 通过我们的操作user表来实现存储我们的数据
        # 实现的是我们的创建我们的超级管理员的方法,我们是必须使用我们的create_superuser
        User.objects.create_superuser(username=username, password=password, email=request.POST.get('email'))
        # 实现创建普通用户的方法
        User.objects.create_user(username=request.POST.get('username'), password=request.POST.get('password'))
        return redirect("/login/")
    return render("register.html")
​
​
"""
我们实现基本的创建的时候,我们使用的常见的方法就是;
create这是我们的普通的创建的方法,密码那些是不会实现加密的
create_user 实现的就是我们的创建一个普通用户,但是最终我们的密码那些都是实现了加密的
craete_superuser 实现的就是我们的创建了一个超级用户,最终的密码这些东西都是实现了加密的
"""

项目的开发流程

1.需求分析

先实现我们的确定用户的基本的需求以及一些初步使用的方案

2.项目设计

首先先确定我们的项目完成需要的语言有哪些,然后使用的架构有哪些,使用的开发框架有哪些,需要的完成的功能有哪些等等

3.分组开发

不同的人来实现我们的功能的开发,然后实现解决明显bug

4.测试开发

就是来实现的是我们的测试是否含有问题,启动是否有问题

5.交付上线(部署上线)

交付上线后的问题就是运维的事情