首先是utils包:
functions.py配置代码如下:
from flask_sqlalchemy import SQLAlchemy
from flask_debugtoolbar import DebugToolbarExtension
from flask_restful import Api
from flask_marshmallow import Marshmallow
db = SQLAlchemy()
debugtoolbar = DebugToolbarExtension()
api = Api()
ma = Marshmallow()
def get_db_uri(DATABASE):
user = DATABASE.get('USER')
password = DATABASE.get('PASSWORD')
host = DATABASE.get('HOST')
port = DATABASE.get('PORT')
name = DATABASE.get('NAME')
db = DATABASE.get('DB')
driver = DATABASE.get('DRIVER')
return '{}+{}://{}:{}@{}:{}/{}'.format(db, driver, user, password, host, port, name)
def init_ext(app):
# 对app进行初始化SQLALCHEMY
db.init_app(app=app)
# 对app进行初始化debugtoolbar
debugtoolbar.init_app(app=app)
# 对app进行初始化restful.Api
api.init_app(app=app)
# 对app进行初始化Marshmallow
ma.init_app(app=app)
setting.py配置代码如下:
import os
from utils.functions import get_db_uri
# 基础路径
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 页面模板
templates_dir = os.path.join(BASE_DIR, 'templates')
# 静态模板
static_dir = os.path.join(BASE_DIR, 'static')
DATABASE = {
# 用户
'USER':'root',
# 密码
'PASSWORD':'123456789',
# 地址
'HOST':'localhost',
# 端口
'PORT':'3306',
# 数据库
'DB':'mysql',
# 驱动
'DRIVER':'pymysql',
# 数据表名称
'NAME':'flask3'
}
# 以下执行的函数正确的去拼接成了flask识别的配置格式, 结果为字符串,方便给App.py里面的app.config['SQLALCHEMY_DATABASE_URI']调用
SQLALCHEMY_DATABASE_URI = get_db_uri(DATABASE)
App.py配置代码如下:
from flask import Flask
from Stu.views import stu
from Grade.views import grade
from utils.functions import init_ext
from utils.setting import templates_dir, static_dir, SQLALCHEMY_DATABASE_URI
def create_app():
app = Flask(__name__,
template_folder=templates_dir,
static_folder=static_dir)
app.debug = True
app.register_blueprint(blueprint=stu, url_prefix='/stu')
app.register_blueprint(blueprint=grade, url_prefix='/grade')
app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI
#上面调用函数得到的结果: app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456789@localhost:3306/flask3'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 配置debugtoolbar必须填写
app.config['SECRET_KEY'] = 'secret_key'
# 第一种初始化方法
# SQLAlchemy(app=app)
# 第二种初始化方法, 此方法调用函数init_ext(app)同时对app进行了SQLAlchemy和debugtoolbar的初始化
init_ext(app)
# 最重要的操作都是对app进行初始化的, db=SQLALCHEMY()这个对象并没有被改变
return app
manage.py项目文件配置如下:
from utils.App import create_app
from flask_script import Manager
# 此为项目启动文件, 越精简越好!
app = create_app()
manage = Manager(app=app)
if __name__ == '__main__':
manage.run()
定义模型映射数据库:
Stu包下的models.py:
from utils.functions import db
class Student(db.Model):
s_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
s_name = db.Column(db.String(20), unique=True)
s_age = db.Column(db.Integer, default=18)
s_g = db.Column(db.Integer, db.ForeignKey('grade.g_id'), nullable=True) # 指定顺序不能混乱, 必须按照这种顺序进行参数匹配
__tablename__ = 'student'
def __init__(self, name, age):
self.s_name = name
self.s_age = age
sc = db.Table('sc',
db.Column('s_id', db.Integer, db.ForeignKey('student.s_id'), primary_key=True),
db.Column('c_id', db.Integer, db.ForeignKey('course.c_id'), primary_key=True)
)
class Course(db.Model):
c_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
c_name = db.Column(db.String(10), unique=True)
students = db.relationship('Student',
secondary=sc, #定义中间表
backref='course')
__tablename__ = 'course'
def __init__(self, name):
self.c_name = name
Grade包下的models.py:
from datetime import datetime
from utils.functions import db
class Grade(db.Model):
g_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
g_name = db.Column(db.String(10), unique=True)
g_desc = db.Column(db.String(100), default=None) # 或者nullable=True
g_time = db.Column(db.DATE, default=datetime.now())
students = db.relationship('Student', backref='grade', lazy=True) # 参数依次表示:模型名称, 反向加载的连接, 懒加载
__tablename__ = 'grade'
def __init__(self, name, desc):
self.g_name = name
self.g_desc = desc
在Stu下的 StuMarshmallow.py 进行序列化操作!
from utils.functions import ma
# 序列化--->serialize
# 自定义序列化对象
class StuMarsh(ma.Schema):
class Meta:
# 在flask里面fields必须写!!
fields = ['s_name', 's_age']
stumarsh = StuMarsh()
Stu包下的views.py:
import random
from flask import Blueprint, render_template, request, redirect, url_for
# sqlalchemy里面的and_, or_, not_方法, app都是经过SQLAchemy()进行初始化的, 所以这里面的方法都能够被使用!
from sqlalchemy import and_, or_, not_
from Stu.models import Student, Course
from utils.functions import db
from flask_restful import Resource
from utils.functions import api
from Stu.StuMarshmallow import stumarsh
stu = Blueprint('stu', __name__) #初始化stu
@stu.route('/')
def index():
return render_template('index.html')
# 创建数据表
@stu.route('/createdb/')
def create_db():
db.create_all()
return '创建数据表成功'
# 删除数据表
@stu.route('/dropdb/')
def drop_db():
db.drop_all()
return '删除数据表成功'
# 创建学生信息
@stu.route('/createstu/', methods=['GET', 'POST'])
def create_stu():
if request.method == 'GET':
return render_template('create_stu.html')
elif request.method == 'POST':
username = request.form.get('username')
age = request.form.get('age')
stu = Student(username, age) #创建学生对象
db.session.add(stu) # 将学生对象加入数据库中 -->缓存中
# 处理异常
try:
db.session.commit() # 提交到数据库 -->执行
return '数据库操作成功'
except:
db.session.rollback() # 回滚数据 -->执行
return '数据库操作失败, 数据已经回滚'
# 批量创建学生信息
@stu.route('/createstus/', methods=['GET', 'POST'])
def create_stus():
if request.method == 'GET':
return render_template('create_stus.html')
elif request.method == 'POST':
stus_list = []
username1 = request.form.get('username1')
age1 = request.form.get('age1')
username2 = request.form.get('username2')
age2 = request.form.get('age2')
stu1 = Student(username1, age1)
stu2 = Student(username2, age2)
stus_list.append(stu1)
stus_list.append(stu2)
db.session.add_all(stus_list) # 将列表里面的所有学生对象添加到缓存中 --> 缓存
db.session.commit() # 提交到数据库
return '创建成功'
@stu.route('/createstubyrange/')
def create_random_stus():
stus_list = []
for i in range(20):
stu = Student('小明%s' % random.randrange(1000), random.randrange(30))
stus_list.append(stu)
db.session.add_all(stus_list)
db.session.commit()
return '创建成功'
@stu.route('/selectstu/')
def select_stu():
# 年龄小于16岁的学生的信息, 用逻辑运算符方法
# stus = Student.query.filter(Student.s_age < 16)
# lt le用法 小于, 小于等于
# stus = Student.query.filter(Student.s_age.__lt__(16))
# stus = Student.query.filter(Student.s_age.__le__(16))
#gt ge 大于, 大于等于
# stus = Student.query.filter(Student.s_age.__gt__(16))
# stus = Student.query.filter(Student.s_age.__ge__(16))
# 年龄在16, 1, 20, 34, 23, 32的学生, in_方法
# stus = Student.query.filter(Student.s_age.in_([16, 1, 20, 34, 23, 32]))
# 获取所以学生信息 用SQL语句
# sql = 'select * from student;'
# stus = db.session.execute(sql)
# 按照id降序排列 对象.query.order_by limit取前三个 offset为跳过几个信息开始
# stus = Student.query.order_by('-s_id').limit(3)
# stus = Student.query.order_by('-s_age').offset(1).limit(5)
# stus = Student.query.order_by('-s_age').offset(2)
# 获取id等于24的学生
stus = Student.query.filter(Student.s_id==24) # -->返回对象的列表, 可以迭代
# stus = Student.query.get(24) # --> 返回具体的对象,不可迭代
# 查询多个条件, and_(并且), or_(或者), not_(非,只能写一个条件)
# stus = Student.query.filter(Student.s_age==18, Student.s_name=='小明')
stus = Student.query.filter(and_(Student.s_age==18, Student.s_name=='小明'))
stus = Student.query.filter(or_(Student.s_age==18, Student.s_name=='王羲之'))
stus = Student.query.filter(not_(Student.s_age == 18), and_(Student.s_name=='王羲之'))
return render_template('student_list.html', stus=stus)
@stu.route('/stupage/')
def stu_page():
page = int(request.args.get('page', 1)) # 利用?page=2在域名上可以进行赋值
per_page = int(request.args.get('per_page', 10)) # 每页默认10条
print(page,per_page)
paginate = Student.query.order_by('-s_id').paginate(page=page,per_page=per_page, error_out=False) # 分页器
stus = paginate.items # 获取当前分页数据
return render_template('stupage.html', paginate=paginate, stus=stus)
@stu.route('/selectgradebystu//')
def select_grade_by_stu(id):
stu = Student.query.get(id)
grade = stu.grade
return render_template('gradepage.html', stu=stu, grade=grade)
@stu.route('/addcourse/')
def add_course():
courses = ['高等数学', '线性代数', '大学英语', '大学物理', 'Vfox', '毛概', '建筑设计']
course_list = []
for course in courses:
cou = Course(course)
course_list.append(cou)
db.session.add_all(course_list)
db.session.commit()
return '添加课程成功'
@stu.route('/selectcourse/', methods=['GET', 'POST']) # ---> manytomany 多对多
def stu_cou():
if request.method == 'GET':
stus = Student.query.all()
cous = Course.query.all()
return render_template('stu_cou.html', stus=stus, cous=cous)
if request.method == 'POST':
# 第一种添加方式
student_id = request.form.get('student')
course_ids = request.form.getlist('course')
# sql = 'insert into sc values(%s, %s)' % (student_id, course_id)
# db.session.execute(sql)
# db.session.commit()
# 第二种添加方式
# stu = Student.query.get(student_id)
# cou = Course.query.get(course_id)
# stu.course.append(cou) # 学生去查找对应的课程然后append需要添加的课程 相反也可以通过 cou去找对应的学生, 在点上对应的学生
# db.session.add(stu) # -->可要可不要的步骤
# db.session.commit()
# 第三种添加方式, 群奶
stu = Student.query.get(student_id)
for course_id in course_ids:
cou = Course.query.get(course_id)
stu.course.append(cou)
db.session.commit()
return '插入成功'
@stu.route('/allstu/')
def all_stu():
stus = Student.query.all()
return render_template('all_stu.html', stus=stus)
@stu.route('/stutocourse/')
def stu_to_course(id):
stu = Student.query.get(id)
cous = stu.course
return render_template('stutocourse.html', cous=cous, stu=stu)
@stu.route('/deletecoursebyid///')
def delete_course_by_id(s_id, c_id):
stu = Student.query.get(s_id)
cou = Course.query.get(c_id)
cou.students.remove(stu)
db.session.commit()
return redirect(url_for('stu.all_stu'))
class HelloStudent(Resource):
def get(self, id):
stu = Student.query.get(id)
# 一. 没有经过序列化的, 必须包装成字典才能够正常的去返回
# data = {
# 'name':stu.s_name,
# 'age': stu.s_age,
#
# }
# return {'data': data}
# 二. 经过序列化的
return stumarsh.jsonify(stu)
api.add_resource(HelloStudent, '/api/stu//' ) # api接口访问的路由是在第二个参数, 通过这个路由去访问的返回的结果必须是json格式
Grade包下的views.py
from flask import Blueprint, render_template
from utils.functions import db
from Grade.models import Grade
grade = Blueprint('grade', __name__)
@grade.route('/')
def get_grade():
return 'xxxx'
@grade.route('/createdb/')
def create_db():
db.create_all()
return '创建班级成功'
@grade.route('/creategrade/')
def create_grade():
grades = []
dict1 = {'Java':'Java最牛批', 'Python':'Python最可爱', 'Html5':'Html5妹子多'}
for k,v in dict1.items():
gra1 = Grade(k, v)
grades.append(gra1)
db.session.add_all(grades)
db.session.commit()
return '添加成功'
@grade.route('/selectstubygrade//')
def select_stu_by_grade(id):
grade = Grade.query.get(id)
stus = grade.students
return render_template('grade_student.html',
stus=stus,
grade=grade)