El marco del matraz de python

Aprendiendo
inserte la descripción de la imagen aquí

Crear e instalar un entorno virtual

dos caminos
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

el segundo

# 先打开cmd 中断
# 查看virtual是否安装过
pip show virtualenv 
# 安装
pip install virtualenvwrapper-win
# workon 查看虚拟环境
vorkon
# 切换虚拟环境
# workon 虚拟环境 
# mkvirtualenv 创建新的虚拟环境
mkvirtualenv falsk2env
# 删除虚拟环境
#rmvirtualenv flask2env
#进入虚拟环境
workon flask2env

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Crear un proyecto Flask

La versión profesional de la versión comunitaria de pychram
inserte la descripción de la imagen aquí
debe crearse manualmente
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

from flask import Flask, render_template, jsonify

app = Flask(__name__)
# 路由可以多个对一个视图函数的
@app.route('/')
@app.route('/index/')
def index():
    # 返回值
    # 直接返回
    # return '<b>ZEN</b>'
    # 模板渲染
    # return render_template('index.html',name='123')
    # 返回json对象
    # return {'name':'Ares-Wang','Sex':'男'}
    # 返回json序列化
    return jsonify({
    
    'name':'Ares-Wang','Sex':'男'})

@app.route('/')
def home():
    return 'ARES-ZEN'
if __name__ == '__main__':
    app.run(host='0.0.0.0',debug=True)

inserte la descripción de la imagen aquí

<!-- 引入css样式表    相对路径, 从根目录 -->
<!--    <link rel="stylesheet" href="../static/CSS/index.css">-->
<!--    <link rel="stylesheet" href="/static/CSS/index.css">-->
    <link rel="stylesheet" href="{
     
     {url_for('static',filename='CSS/index.css')}}">

División del proyecto Flask

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

# app.py
from APP import Create_App
app = Create_App()
if __name__ == '__main__':
    app.run(host='0.0.0.0',debug=True)


# views.py
# views.py   路径  +   视图函数
from flask import Blueprint
from .models import *
blue = Blueprint('BlueName', __name__)
@blue.route('/')
def Home():
    return 'SPlIT'


# __init__.py
# __init__.py :初始化文件、创建Flask应用
from flask import Flask
from .views import blue
def Create_App():
    # 返回Flask对象
    app = Flask(__name__)
    # print(app.config)
    # SECRET_KEY 是对称加密的密钥,存在浏览器的
    # session['xxx']='123',session 通过secret_key 把123 加密存在服务器端
    # 同时客户端cookie中存入cookieID 也是加密的 session 设置要配置secret_key
    # app.config['SECRET_KEY']='ZEN'
    # 设置session过期时间
    # app.config['PERMANENT_SESSION_LIFEATIME']=datetime.timedelta
    # 注册蓝图 可以注册多个蓝图
    app.register_blueprint(blueprint=blue)
    return app

parámetros de enrutamiento

@app.route('/xxx/convertidor:nombre_variable')

convertidor: cadena de tipo de parámetro
: aceptar cualquier cadena sin barra inclinada '/' tipo de parámetro predeterminado
int: aceptar número entero
flotante: aceptar ruta de número de punto flotante
aceptar ruta, aceptar barra inclinada ('/') cadena
uuid solo aceptar cadena uuid, código único, cualquiera que es el mismo que el GUID raíz de una regla de generación,
puede especificar varias rutas al mismo tiempo y limitarlas

@app.route('/student//') es lo mismo que @app.route('/student/string:username/')

@app.route('/estudiante/int:id/')
def get_student(id):
estudiante= Estudiante.consulta.get(id)

@app.ruta('/estudiante/uuid:id/')

@app.route('/estudiante/float:num/')

@app.route('/estudiante/ruta:ruta/')

@app.route('/estudiante/<cualquiera('hombre', mujer)>/')

Método de solicitud Común POST GET
Flask admite GET de forma predeterminada, pero no admite
@app.route('/student/') para solicitudes POST

Tanto las solicitudes de obtención como las de publicación son compatibles
@app.route('/estudiante/', métodos=['GET', 'POST'])

Objeto de solicitud y respuesta de solicitud de objeto de respuesta

pedido

Después de que el servidor acepte la solicitud del cliente, creará automáticamente un objeto de solicitud , creado por el marco FLask, y el objeto de solicitud no se puede modificar.

# requests 爬虫测试下面的请求对象
import requests
request = requests.get('http://127.0.0.1:5000/index/?user=123')
request = requests.post('http://127.0.0.1:5000/index/',data={
    
    'user':3456})
print(request.text)

inserte la descripción de la imagen aquí

from flask import Flask,request
@app.route('/index/>',methods=['GET',  'POST'])
def get_index():
	# 获取请求方式
	print(request.method)
	# url 完整请求地址    
	print(request.url)   		# http://127.0.0.1:5000/index/?user=123'
	# base_url   去掉get参数的url
	print(rquest.base_url)		# http://127.0.0.1:5000/index/
	# host_url   只有主机名和端口号
	print(rquest.host_url)		# http://127.0.0.1:5000/
	# remote_addr   请求的客户端地址
	print(request.remote_addr)   #IP地址
	# files 文件上传
	print(request.files)
	# 用户代理, 包括浏览器和操作系统的信息  反爬用的    类似 python-requests/2.31.0
	print(request.user_agent)
	# headers 请求头
	print(request.headers)
	# headers 请求中的cookie
	print(request.cookies)
	# 获取请求参数  get 请求,返回是字符串
	# request.args.get(key,defaultValue)   如果key,没有传参,可以赋默认值,
	print(request.args.get(key))
	# 返回是ImmutableMultiDict类型
	print(request.args)
	# 获取请求参数  post 请求
	print(request.from.get(key))
	#返回是ImmutableMultiDict类型
	print(request.from)

inserte la descripción de la imagen aquí


inserte la descripción de la imagen aquí
Respuesta de respuesta de tipo ImmutableMultiDict

# 导入模板渲染用的包
from flask import render_template, jsonify, make_response,Response
@app.route('/response/')
def  get_Response():
	# 响应的几种方式
	# 1、返回字符串(不常用)
	return 'AresZEN'
	# 2、模板渲染(前后端分离) 在templates中创建模板 xx.html  中jinja2语法 {
    
    {}}  
	return render_template('xx.html',param1='' , param2='')
	# 3、返回json数据(前后端分离)
	return {
    
    'name':'Ares','age':30}
	# jsonify()  序列号    josn=>字符串
	return jsonify({
    
    'name':'Ares','age':30})
	# 4、自定义Response对象
	html= render_template('xx.html',param1='' , param2='')
	# 返回字符串(html格式的字符串)
	print(html,type(html))
	#  导入包make_response(返回的数据,状态码)
	res=make_response(html,200)   
	res = Response(html)
	res.set_cookie()  #  设置cookie
	#  上面任意一个都可以
	return res

redirigir redirigir

@blue.route('redirect')
def make_redirect():
	# 重定向的几种方式
	# return redirect('https://www.baidu.com')
	# return redirect('/路由/')   #  在程序中跳转

	# url_for():反向解析,通过视图函数名反过来找路由
	# url_for('蓝图名称.视图函数名')  #  注意是蓝图名称 ,不是蓝图对象   blue对象 = Blueprint('BlueName蓝图名称', __name__)
	# ret = url_for('蓝图名称.视图函数名')
	# return redirect(rect)

	# url_for 传参
	ret= url_for('蓝图名称.视图函数名',参数名=Value,参数名2=Value2)
	return redirect(rect2)

Cookie de sesión y tecnología de sesión

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
poner galletas
inserte la descripción de la imagen aquí

Obtener
solicitud de cookie.cookies.get(clave)
eliminar
respuesta de cookie.delete_cookie(clave)

Las cookies no pueden guardar chino

sesión

Sesión Tecnología de sesión del lado del servidor, que depende de
las características de las cookies:
- Tecnología de sesión del lado del servidor
- Todos los datos se almacenan en el servidor
- Almacenados en la memoria de forma predeterminada
- Estructura de almacenamiento: forma clave-valor, par clave-valor
- la sesión no puede hacer sin cookie
: almacenamiento de ID de sesión En el lado del cliente, el valor de la sesión existe en el lado del servidor
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

session set
session['key']='value'
to get session Si no existe, devolver el valor especificado por defecto
session.get(key,default=None)
eliminar sesión
session.pop(key) eliminar cierto valor
session .clear( ) borrar todas las sesiones
inserte la descripción de la imagen aquí

cookie VS cookie de sesión
: ① almacenada en el cliente (navegador) ② baja seguridad ③ puede reducir la presión del servidor
sesión: ① almacenada en el servidor (servidor) ② alta seguridad ③ mayores requisitos en el servidor ④ aún necesita confiar en las cookies El ID de sesión generado por el servidor se devolverá al cliente y el ID de sesión se almacenará en el cliente.

Plantilla Plantilla

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Sintaxis de plantilla del motor JinJa2 y paso de parámetros

Hay dos tipos principales de sintaxis de plantilla:

  • variable
  • Etiqueta

Variables en la plantilla { { nombre de la variable }} La variable no existe, se ignora de forma predeterminada y no se informará ningún error.
Los datos pasados ​​a la plantilla por la función de visualización de vistas devuelven render_template('xxx.html', parámetro 1=valor1, parámetro 2=Valor2)

O
datos = { 'edad': 20, 'nombre': 'ZEN' ,pasatiempos:['fútbol', 'baloncesto']} render_template('xxx.html', **datos) template { { edad
}
} { { nombre}}
{ { pasatiempos }} devuelve una cadena de ['fútbol', 'baloncesto'], por lo que generalmente usa un bucle for para obtener el valor

bucle para

{% for hobby in hobbys %}
# segmento
{% else %} #hobby ya no existe, así que ingrese else.

segmento

{% endfor %} debe tener una etiqueta final

Usar para obtener bucle de información de bucle

{% para aficiones en aficiones %}

{ {pasatiempo}}


index:{ { loop.index }} # Subíndice comenzando desde 1
index:{ { loop.index0 }} # Subíndice comenzando desde 0
index:{ { loop.revindex }} # Subíndice inverso, excluyendo 0
index:{ { loop.revindex0 }} # subíndice inverso, incluido 0
index:{ { loop.first }} # determina si es el primer elemento
index:{ { loop.last }} # determina si es el último elemento

Etiquetas en la plantilla {% etiqueta %} Tenga en cuenta que debe haber una etiqueta final Tenga en cuenta que debe haber una etiqueta final
Lógica de control, utilice expresiones externas para crear definiciones de macros variables
{% si edad >=18 %}

adulto

herencia de plantilla

inserte la descripción de la imagen aquí

<!-- 定义Base.html  模板页 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ParentTemplate</title>
    <link rel="stylesheet" href="{
     
     { url_for('static',filename='base.css') }}"/>
    {% block extcss %}
    {% endblock %}
</head>
<body>
    {% block head %}
    {% endblock %}
    {% block content %}
    {% endblock %}
    {% block foot %}
    {% endblock %}
    <script src="{
     
     { url_for('static',filename='baseJS.js') }}"></script>
    {% block extjs %}
    {% endblock %}

</body>
</html>

Excavando en la plantilla principal

<!-- 定义inc.html  -->
<hr>
<h4>include文件</h4>
<hr>
<!-- 定义1.html  继承模板Base.html页 -->
{% extends 'Base.html'%}

{% block extcss %}
    <link rel="stylesheet" href="{
     
     { url_for('static',filename='index.css') }}"/>
{% endblock %}
{% block head %}
<p>我是head标签</p>
{% endblock %}
{% block content%}
	{% include 'inc.html' %}
	<p>AAA</p>
{% endblock %}

Rellenar huecos en subplantillas

Haga un agujero en la plantilla principal Base.html, complete la inclusión en la plantilla secundaria 1.html
e incluya otro html

{% extends '1.html' %}
{% block content %}
{
   
   {super()}}
<p>AresZEN</p>
{% endblock %}
{# 定义 Python函数}
{% macro person(name.age) %}
	<b>姓名:{
   
   { name }}, 年龄:{
   
   { age }} </b>
{% endmarco %}

{% block foot %}
	{
   
   { person('ZEN',27) }}
{% endblock %}
<!-- 定义2.html  继承模板1.html页 ,1.html又继承Base.html-->
{% extends '1.html' %}

{% block content %}
	<!-- 把父模版内容保留下来 -->
	{
   
   {super()}}
	<p>AresZEN</p>
{% endblock %}

inserte la descripción de la imagen aquí

base del modelo

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Instale matraz_sqlalchemy (para ORM)
pip install matraz_ sqlalchemy -i https://pypi.douban.com/simple
install matraz_migrate (para la migración de datos para migrar el modelo de base de datos a la base de datos)
pip install matraz_migrar -i https://pypi. douban.com/simple
install pymysql (controlador mysql)
pip install pymysql -i https://pypi.douban.com/simple

El uso de ORM
para conectarse a la base de datos en Flask necesita especificar la configuración

Definición de modelo de base de datos
Un modelo de base de datos corresponde a una tabla en una base de datos, y todos los modelos de base de datos deben basarse en la clase base Modle del objeto ORM, es decir, db.Model

#   models.py   模型  数据库
# 创建数据库模型
#	模型 	=》		数据库
#	类	 	=》		表结构
#	类属性 	=》		表字段
#	一个对象 =》		表的一个行数据
from .exts import db
class Account(db.Model):
	# 定义数据库的表名
	__tablename__ = "account"
	id = db.Column(db.Integer,primary_key=True, autoincrement=True)
	account = db.Column(db.String(10),unique=True,nullable=False)
	username = db.Column(db.String(30),nullable=False)
	# 定义显示信息   在模型类中,重写   __repr__   方法, 
    def __repr__(self):
        """定义之后,可以让显示对象的时候更直观"""
        return "User object : username =%s" % self.username 

# exts.py  插件管理


# 1、导入第三方插件
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

# 2、 初始化对象
db = SQLAlchemy()   # ORM
migrate = Migrate() # 数据迁移

# 3、与app对象绑定
def init_exts(app):
    db.init_app(app=app)
    migrate.init_app(app=app,db=db)
#   __init__.py :初始化文件、创建Flask应用
import datetime

from flask import Flask

from .views import blue

from .exts import init_exts
def Create_App():
    # 返回Flask对象
    app = Flask(__name__)
    # ORM 数据库配置
    # SQLite 数据库连接不需要额外驱动,也不需要用用户名和密码  SQLite 一般是手机程序用的  本地数据库
    DB_URI='sqlite:///sqlite3.db'
    app.config['SQLALCHEMY_DATABASE_URI']=DB_URI # 配置连接数据库路径DB_URI
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False   # 禁用对象追踪修改
    # 初始化插件
    init_exts(app=app)
    # 注册蓝图 可以注册多个蓝图
    app.register_blueprint(blueprint=blue)
    return app```

inserte la descripción de la imagen aquí
Migración de datos: Es crear una tabla en el modelo modelo en la base de datos

  1. Primero ingrese el directorio del proyecto en cmd o Terminal (puede arrastrar el proyecto seleccionado a la terminal) (el directorio donde se encuentra app.py)
  2. Volver a ejecutar el siguiente comando
    1. matraz db init #Crear carpeta de migración migra, solo se puede ejecutar una vez
    2. db del matraz migrar #Generar archivo de migración
    3. Flash db upgrade # Ejecute la actualización del archivo de migración y la base de datos tendrá una tabla. Si la estructura de la tabla cambia, debe ejecutar esto para aplicar los cambios en la migración a la base de datos.
    4. Flash db downgrade # realizar una degradación en el archivo

inserte la descripción de la imagen aquí

Antes de configurar mysql, esta base de datos debe existir
DB_URI='mysql+pymysql://root:root@localhost:3306/data name'

La operación CRUD de la tabla
necesita operar el modelo de datos en la función de vista, sincronizando así la base de datos

#  views.py 中
# 蓝图
from flask import Blueprint,render_template,request
from .models import *

# 蓝图
blue = Blueprint('bluename',__name__)
@blue.route('/')
def index():
	return render_template('index.html')
# 表单操作:CRUD操作
@blue.route('/accountadd/',methods=['GET','POST'])
def account_add():
	# 添加一个记录   Account 是类,定义在models.py
	u = Account()
	if request.method=='GET':
		u.account = request.args.get('account')
		u.username = request.args.get('username')
	else:
		u.account = request.from.get('account')
		u.username = request.from.get('username')	
	#  views.py中没有导入 exts为啥油db对象,因为db对象在models.py 导入了。   因此 views中导入model,相当于也导入了exts
	db.session.add(u)  			# 将u对象添加到session中	
	db.session.commit()			# 同步到数据库中
	return 'success!'

@blue.route('/accountaddall/')
def account_add():
	# 添加多条记录   Account 是类,定义在models.py
	users = []
	for i in range(1,10):
		u=Account()
		u.account = 'ZEN_'+str(i)
		u.username = 'Ares_'+str(i)	
		users.append(u)	
	#  views.py中没有导入 exts为啥油db对象,因为db对象在models.py 导入了。   因此 views中导入model,相当于也导入了exts
	# db.session.add_all(对象列表)
	try:
		db.session.add_all(users)  			# 将u对象列表添加到session中	
		db.session.commit()					# 同步到数据库中   事务提交
	except Exception as e:
		db.session.rollback()				# 回滚
		db.session.flush()					# 把session中数据清理掉											
		return 'fail: '+ str(e)
	return 'success!'

@blue.route('/accountdelete/')
def account_del():
	try:
		u=Account.query.first() # 查询第一条数据
	    db.session.delete(u)
	    db.session.commit()
	 except Exception as e:
	 	db.session.rollback()
	 	db.session.flush()  
    return 'success!'
 
@blue.route('/accountupdate/')
def account_update():
	try:
		u=Account.query.first() # 查询第一条数据
		u.username='yyds'	   
	    db.session.commit()
	 except Exception as e:
	 	db.session.rollback()
	 	db.session.flush()  
    return 'success!'



#  查询数据
@blue.route('/userget/')
def user_get():

	# all(): 以列表形式返回查询的所有结果,返回列表
	# users = Account.query.all()
	# first() 返回查询的第一个结果,如果没有结果,则返回None
	# user = Account.query.first()   可以继承  过滤器
	# filter() 把过滤器添加到原查询上,返回一个新查询,可以继续   . 过滤器
	# users = Account.query.filter()   可以继承  过滤器
	# user = Account.query.filter(Account.username=='yyds')
	# filter_by() 把**等值**过滤器添加到原查询上,返回一个新查询
	
	#  filter_by() 与  filter()  区别
	
	# user = Account.query.filter_by(username='yyds')
	# count() 返回查询结果的数量
	# users = Account.query.filter()  可以继承  过滤器
	print(users.count())
	# first_or_404() 返回查询的第一个结果,如果没有结果,则终止请求,返回404错误响应
	# user = Account.query.filter_by(username='yyds').first_or_404()
	# get()  返回指定主键对应的行,如果没有对应的行,则返回None ,此处家人username是主键
	# user = Account.query.get(username='yyds')
	# get_or_404()  返回指定主键对应的行,如果没有找到指定的主键,则终止请求,返回404错误响应
	#user = Account.query.get(username='yyds')
	# limit()  取前面几条 使用指定的值限制原查询返回的结果数量,返回一个新查询  可以继承 过滤器
	# offset() 跳过前几条 偏移原查询返回的结果,返回一个新查询  ,可以继承  过滤器
	# users = Account.query.offset(3).limit(4)
	# order_by()   排序  升序
	# users = Account.query.order_by('id')
	# order_by()       排序     降序     需要到包   from sqlalchemy import desc
	# users = Account.query.order_by(desc('id'))
	
	# 逻辑运算符   and_    ,    or_     ,  not_
	users = Account.query.filter(Account.username='yyds' , Account.id < 100)    #  且    默认
	#   需要到包   from sqlalchemy import and_ , or_ , not_
	users = Account.query.filter(and_(Account.username='yyds', Account.id < 100) #  且
	
	#  查询属性
	# contains   模糊查询   类似 sql  like
	users = Account.query.filter(Account.username.contains('yd'))
	# in_()   其中只有   类似  sql  in
	users = Account.query.filter(Account.username.in_(['yyds','jjz']))
	# startswith():			以某字符串开头
	# endswith():			以某字符串结尾
	users = Account.query.filter(Account.username.startswith('yy'))
	
	# __gt__     大于
	# __ge__     大于等于
	# __lt__	 小于
	# __le__	 小于等于
	users = Account.query.filter(Account.id.__gt__(300))
    return 'success!'

paginación

inserte la descripción de la imagen aquí

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<ul>
	{%  for item in Accounts %}
	    <li>{
   
   { item.username }}</li>
	{% endfor %}
</ul>
</body>
</html>
@blue.route('/paginate/')
def get_info():
    page = int(request.args.get('page', 1))
    per_page = int(request.args.get('per_page', 5))
    Accounts = Account.query.paginate(
        page=page,
        per_page=per_page
    ).items
    return render_template('info.html', Accounts)

Asociación de varias tablas


##  model.py   一对多 案例
# models.py   模型  :和数据库相关的
from .exts import db
"""
 department :employee =》 1:N     1对多
外键要设置在 N: 多的 一个表  
"""
# 创建 department 部门表 即 Department 模型
# 模型需要继承db.Model,否则就普通的类
class Department(db.Model):
	# 表名
	__tablename__ = 'department'
	id = db.Column(db.Integer, primary_key=True, autoincrement=True)
	# 部门编号
	deptCode = db.Column(db.String(30), nullable=False)

	# 建立关联
	#		第一个参数:关联的模型名,因python语言是解释性语言,Employees, 需要需要 用  ''
	#		第二个参数:反向引用的名称,department 对象
	#				让employee去反过来得到department对象的名称    employee.department  是个department对象
	#		第三个参数: 延迟加载,懒加载,    用到的时候,才会建立关系,懒加载:为了提高性能,节约资源
	# 这里departments不是字段,不是字段 是类的属性
	employees = db.relationship('Employees', backref='department', lazy=True)

	"""
	查询员工所属的部门,反向引用department
	emp = Employee.query.get('emp_Code值')
	#  department 要跟  backref对应的值保持一致   
	#  emp.department   返回是department对象
	dept = emp.department   
	code=dept.deptCode	
	查询某部门下面的所有员工
	dept = Department.query.get('deptCode值')
	dept.employees  #  所有部门编码下的员工信息  返回是employee 对象列表
	"""
# 创建employee 员工表 即 Employee 模型
# 模型需要继承db.Model,否则就普通的类
class Employee(db.Model):
	# 表名
	__tablename__ = 'employee'
	id = db.Column(db.Integer,  autoincrement=True)
	# 员工姓名
	emp_name = db.Column(db.String(30), nullable=False)
	# 员工编号
	emp_Code = db.Column(db.String(30),nullable=False, unique=True, primary_key=True)

	# 外键 也是字段,  跟 员工表的 员工编号关联  1:N  外键也放在N的表中
	# 实现一对多关系,要在对应的表 添加 db.relationship
	department = db.Column(db.String(30),db.ForeignKey(Department.deptCode), nullable=False, unique=True)


inserte la descripción de la imagen aquí

Tabla de relaciones de muchos a muchos N:M

N:M relación de muchos a muchos, también hay una tabla intermedia entre dos tablas: asociación
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

# models.py
from .ext import db
# usermodel  和  usermodel  建立关联表
collect = db.Table(
	# 表名
	'collects',
	#  组合主键
	# 字段
	db.Column('user_id',db.Integer,db.ForeignKey('usermodel.id'),primary_key=True)
	db.Column('sysmodel_id',db.Integer,db.ForeignKey('sysmodel.id'),primary_key=True)
)
# 用户表
Class UserModel(db.Model):
	__tablename__='usermodel'
	# 字段
	id = db.Column(db.Integer,primary_key=True,autoincrement=True)
	username = db.Column(db,String(30))
	userCode = db.Column(db.String(30),)
# 系统模块
Class SysModel(db.Model):
	__tablename__:'sysmodel'
	id = db.Column(db.Integer,primary_key=True,autoincrement=True)
	name = db.Column(db.String(30))
	# 关联
	# secondary=collect:  设置中间表
	users =db.relationship('UserModel',backref='sysmodels',lazy=True,secondary=collect)
# views.py   
"""
用户表和系统模块表 追加数据略
"""
@blue.route('/addcollect/')
def add_collect():
	# 用户拥有的系统模块
	user = UserModel.query.get('key')
	sysmodel = SysModel.query.get('key')
	# user.sysmodels 是反向查询的  backref='sysmodels'
	user.sysmodels.append(sysmodel)
	db.session.commit()
	return 'success!'

@blue.route('/getcollect/')
def get_collect():
	# 查询某用户拥有的系统模块
	user = UserModel.query.get('key')
	print(user.sysmodels)  #  返回list
	# 查询系统模块拥有的用户
	sysmodel = SysModel.query.get('key')
	print(sysmodel.users) # 返回是查询集  可以继续用filter 、filter_by过滤方法
	print(list(sysmodel.usrs))  返回list
@blue.route('/deluser/')
def del_user():
	# 多对对 关联删除是级联删除,跟1对多删除不一样, 1对多, 1的一方删除数据,多的一方 对应数据外键 null
	user = UserModel.query.get('key')
	db.session.delete(user)
	db.session.commit()
	#  删除用户,对应用户在中间表collect中记录也会删除。

inserte la descripción de la imagen aquí

Almacenamiento en caché de matraz de valor de administración de complementos

Instalar:

pip install matraz-caching # es un conector, no un guión bajo

# exts.py  插件管理

# 1、导入第三方插件
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
# 是下划线,不是连接符
from flask_caching import Cache
# 2、 初始化对象
db = SQLAlchemy()   # ORM
migrate = Migrate() # 数据迁移
cache = Cache(config = {
    
    
	'CACHE_TYPE':'simple'
})
# 3、与app对象绑定
def init_exts(app):
    db.init_app(app=app)
    migrate.init_app(app=app,db=db)
    cache.init_app(app=app)

inserte la descripción de la imagen aquí

aplicación de caché

# views.py
# @ 装饰器
@blue.route('/')
@cache.cached(timeout=20)    @ 开始访问(执行里面的代码),第二个方法缓存(不执行代码),缓存有效期20s,超时,会再次访问执行里面的代码
def home():
	print('xxx')
	# 模拟访问复杂的逻辑运算
	time.sleep(5)
	return 'ZEN'

Función de enlace = middleware, similar a la intercepción del marco AOP, similar al punto de montaje en Vue

La función de enlace (Middleware) es la función montada antes de la función de ejecución (función de vista) y la función de destino. El desarrollador del marco proporciona a la persona que llama un punto de montaje, que es una función de enlace común para las ideas de programación de aspectos AOP
.

  1. before_first_request: Ejecutar antes de procesar la primera solicitud
  2. before_request: Ejecutado antes de cada solicitud. Por lo general, use esta función de enlace para preprocesar algunas proporciones, implementar request.user_agent anti-escalada, etc.
  3. after_request: registre una función para ejecutar después de cada solicitud si no se lanzan excepciones no controladas
  4. teardown_appcontext: cuando se elimina el contexto de la aplicación, la función se puede enviar o revertir a la base de datos

Si usa un rastreador para acceder sin anti-rastreo (los encabezados no están configurados con cookies, agente de usuario)
request.user_agent.string # python-requests/2.28.2 resultados similares
inserte la descripción de la imagen aquí

from .exts import *
# views.py 
#钩子函数不需要配置路由
@blue.before_request
def before():
	ip=request.remote_addr
	# cache.get()   cache.set()
	if cache.get(ip):
		# 做了拦截,不会进入视图函数
		return '禁止爬虫访问!'
	else# 对每个IP配置一个缓存,1秒内不让重复访问
		cache.set(ip,'value',timeout=1)
	# string 别忘记
	if "python" in request.user_agent.string:
		return "禁止用python爬虫"
	
	
# @ 装饰器
@blue.route('/')
@cache.cached(timeout=20)    @ 开始访问(执行里面的代码),第二个方法缓存(不执行代码),缓存有效期20s,超时,会再次访问执行里面的代码
def home():
	print('xxx')
	# 模拟访问复杂的逻辑运算
	time.sleep(5)
	return 'ZEN'

inserte la descripción de la imagen aquí

Frasco de objetos incorporados

inserte la descripción de la imagen aquí

# views.py   钩子函数
@blue.before_request
def before():
    # Flask内置对象
    # request :   请求对象
    # session  :  会话对象
    # g    :  global 全局对象
    # current_app   Flask应用对象
    g.xx = 'yyds'

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí
Las plantillas estáticas predeterminadas y __init__.py están en el mismo nivel, si app=Flask( name ) no está en el mismo nivel, debe inicializar app=Flask( name , static_folder='path', template_folder='path')

inserte la descripción de la imagen aquí

Valor de separación de front-end y back-end Flask-RESTful

render_template La representación de plantillas es una mezcla de front-end y back-end.
El webapi basado en el marco MVC en .net está dedicado a la interfaz y al back-end. El marco de trabajo de Python Value Flas proporciona el paquete Flash-Restful.

render_template se usa en views.py, es # Función de vista: el enrutamiento de vista basado en función FBV usa @decorator
Vista de clase: la vista basada en clase CBV no necesita usar separación de back-end, no necesita vistas.py sin enrutamiento @decorator

matraz-reposo

Instalar
pip instalar matraz-reposado

# exts.py  插件管理
# 1、导入第三方插件
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
# 是下划线,不是连接符
from flask_caching import Cache
#  注意是Api
from flask_restfull import Api
# 2、 初始化对象
db = SQLAlchemy()   # ORM
migrate = Migrate() # 数据迁移
cache = Cache(config = {
    
    
	'CACHE_TYPE':'simple'
})
api = Api(# 3、与app对象绑定
def init_exts(app):
    db.init_app(app=app)
    migrate.init_app(app=app,db=db)
    cache.init_app(app=app)
    api.init_app(app=app)

inserte la descripción de la imagen aquí

Cargue __init__.py antes de que se ejecute app.py Se cargarán tres paquetes en init.py
desde
la importación de matraz Flask
– administración de complementos—
desde .exts import init_exts
– enrutamiento—
desde .urls import *

Cree un objeto matraz ejecutando Create_App() en app.py y vincule el complemento al objeto matraz al mismo tiempo

inserte la descripción de la imagen aquí

#	app.py
# Create_APP 写在__init__.py 中,所以导入把 要 包名 APP
from APP import Create_App
app = Create_App()
if __name__ == '__main__':
    app.run(host='0.0.0.0',debug=True)
# __init__.py :初始化文件、创建Flask应用
from flask import Flask
from .exts import init_exts
from .urls import *
def Create_App():
    # 返回Flask对象
    app = Flask(__name__)
    # 初始化插件,创建的app应用,附加了哪些插件
    init_exts(app=app)
    return app

# exts.py  插件管理  三部曲
# 1、导入第三方插件
from flask_restful import Api
# 2、 初始化对象
api=Api()
# 3、与app对象绑定
def init_exts(app):
    api.init_app(app=app)

inserte la descripción de la imagen aquí

# apis.py  接口用的
from flask_restful import Resource
# 类视图  : CBV  Class  Based View
# 视图函数: FBV   Function Based View
# 继承Resource
class StudentResource(Resource):
    def get(self):
        return '我是get 请求'
    def post(self):
        return '我是Post请求'
# urls.py   路由文件
from .exts import api
from .apis import *
#  注册路由				api.add_resource(类视图 ,路由)
api.add_resource(StudentResource,'/stu/')

inserte la descripción de la imagen aquí

formato de campo

Para definir el formato de datos de salida de la interfaz estándar, el formato de campo debe dividirse
en dos pasos:
1. Defina los campos
2. Use @decorator para modificar @marshal_with en la interfaz (el formato de datos que debe devuelto)

Nota:
Si los datos devueltos existen en la estructura predefinida, los datos se devolverán normalmente.
Si los datos devueltos son menores que los campos en la estructura predefinida, los campos predefinidos tendrán valores predeterminados. También se puede establecer el valor predeterminado.Si
los datos devueltos no están en la estructura predefinida, los datos se filtrarán (descartarán) automáticamente.

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

#	apis.py
from flask_restful import Resource,fields,marshal_with

# 输出字段格式
ret_info={
    
    
    'name':fields.String,
    'age':fields.Integer,
    'SchoolName':fields.String,
    'address':fields.String
}
# 输出字段格式
ret_fields={
    
    
    'status':fields.Integer,
    'isSecces':fields.String(default='fail'),
    #  对方用data,其实映射是password数据的值
    'data':fields.String(attribute='password'),
    'msg':fields.String,
    'studentinfo':fields.Nested(ret_info)
}
# 继承Resource
class StudentResource(Resource):
    @marshal_with(ret_fields)
    def get(self):
    	# Student是models.py 需要数据迁移
        stu=Student.query.first()
        return {
    
    
            'status':200,
            'isSecces':'ok',
            'msg':'win',
            'password':'123',
            # Student信息
            'studentinfo':stu
        }

ret_fields2={
    
    
    'status':fields.Integer,
    'isSecces':fields.String(default='fail'),
    #  对方用data,其实映射是password数据的值
    'data':fields.String(attribute='password'),
    'msg':fields.String,
    'studentinfo':fields.List(fields.Nested(ret_info))
}
class StudentALLResource(Resource):
    @marshal_with(ret_fields2)
    def get(self):
    	# Student是models.py 需要数据迁移
        stu=Student.query.all()
        return {
    
    
            'status':200,
            'isSecces':'ok',
            'msg':'win',
            'password':'123',
            # Student信息
            'studentinfo':stu
        }
"""
# 返回的结果
{
    "status": 200,
    "isSecces": "ok",
    "data": "123",
    "msg": "win",
    "studentinfo":[
	    {
			"name":"ZEN",
			"age":33,
			"SchoolName":"家里蹲",
			"address":"中国"
		},   {
			"name":"ZEN1",
			"age":331,
			"SchoolName":"家里蹲1",
			"address":"中国1"
		}
	]

}
"""  
ret_url={
    
    
	'name':fields.String,
	'url':fields.url(endpoint='id',absolute=False)
}
class urlResource(Resource):
    @marshal_with(ret_url)
    def get(self):    	
        return {
    
    
            'name':200,
            'url':'/'                   
        }
"""
# 返回的结果
{
    "status": 200,
    "isSecces": "ok",
    "data": "123",
    "msg": "win",
    "studentinfo":{
		"name":"ZEN",
		"age":33,
		"SchoolName":"家里蹲",
		"address":"中国"
	}

}
"""
# urls.py   路由文件
from .exts import api
from .apis import *
#  路由
api.add_resource(StudentResource,'/')
api.add_resource(urlResource,'/url/',endpoint='id')
api.add_resource(StudentALLResource,'/stuall/')

Análisis de parámetros

Los argumentos se pueden obtener sin publicar: request.form u obtener: request.args. En su lugar, es analizado por reqparse.RequestParser

# apis.py 
from flask_restful import Resource,reqparse
# 参数转换器
parser = reqparse.RequestParser()
parser.add_argument('name',type=str)
parser.add_argument('info',type=str,action='append') # 支持多个info
parser.add_argument('cookiex',type=str,location='cookies') # 获取cookies中数据
class StudentResource(Resource):
    def get(self):
        # 获取参数
        args=parser.parse_args()
        name=args.get('name')
        return {
    
    
            'key':name
        }
# spider.py  爬虫测试
import requests

request = requests.get('http://127.0.0.1:5000/',
                       json={
    
    
                           'name':'23',
                           'info':['123','erew']
                       },
                       headers={
    
    
                           'Content-Type':'application/json'
                       }
                       )
print(request.text)

Supongo que te gusta

Origin blog.csdn.net/u013400314/article/details/131460941
Recomendado
Clasificación