- django是一个大而全的框架,flask是一个轻量级的框架。
- django内部为我们提供了非常多的组件:orm/session/cookie/admin/form/modelform/路由/视图/模板/中间件/分页/auth组件/contenttype/缓存/信号/多数据库连接。
- flask框架本身没有太多的功能:路由/视图/模板(jinja2)/session/中间件,第三方组件非常齐全。
- 【注意事项】django的请求处理是逐一封装和传递;而flask的请求是利用上下文管理来实现的。
第一章:URL与视图、jinja2模板
文件目录结构如下:
config.py文件中内容:
"""配置文件"""
#flask的配置项都是大写
JSON_AS_ASCII=False
app.py文件中内容:
from flask import Flask,jsonify,url_for
from flask import redirect#重定向
from flask import request#获取问号后面的内容
from flask import render_template#渲染模板
import config
app = Flask(__name__)
app.config.from_object(config)#以后所有的配置项都是放在config.py中
@app.route('/')
def index():#首页
return {'username':'张梦姣'}
books=[{"id":1,"name":"三国演义"},
{"id":2,"name":"水浒传"},
{"id":3,"name":"红楼梦"},
{"id":4,"name":"西游记"}]
@app.route('/book/list/')
def book_list():
return jsonify(books)
#指定类型int float string
@app.route('/book/<int:book_id>',methods=['GET','POST'])#提交方式get post
def book_detail(book_id):
for book in books:
if book['id']==book_id:
return book
return f"id为{book_id}的图书没有找到!"
#指定多条路径
@app.route('/book/<any(a,b):url_path>/')
def item(url_path):
return url_path
#通过视图获取url:url_for()
@app.route('/book/list1/')
def book_list1():
for book in books:
book['url']=url_for("book_detail",book_id=book['id'])#(函数名,该函数的参数)
return jsonify(books)
#重定向redirect
@app.route('/profile')
def profile():
#参数传递的两种形式
#1.作为url的组成部分:/book/1
#2.查询字符串:/book?id=1
user_id=request.args.get('id')
if user_id:
return '用户个人中心'
else:
return redirect(url_for("index"),code=302)#暂时性重定向状态码302,永久性重定向301
#渲染
@app.route('/about/')
def about():
context={
'username':'ZMJ',
'books':['红楼梦','三国演义','西游记','水浒传'],
'age':18,
"person":{'name':'zmj','age':18},
}
return render_template("about.html",**context)#html文件默认从templates文件夹下面,**context是解包,传递变量
@app.route('/模板继承/')
def 模板继承():
return render_template('index.html')
@app.route('/index1/')
def index1():
return render_template('index.html')
if __name__ == '__main__':
app.run()
base.html文件中内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>{#留取空间,且取名为title#}
{% block head%}{% endblock %}
</head>
<body>
<ul>
<li>
<a href="/">首页</a>
</li>
<li>
<a href="/book/list/">图书列表</a>
</li>
<li>
<a href="/about">关于我</a>
</li>
</ul>
{% block body %}{% endblock %}
<footer style="background-color: #ccc">我是底部的</footer>
</body>
</html>
forms.py文件中内容:
{% extends 'base.html'%}{#继承模板base.html#}
{% block head %}
宏模板
{% endblock %}
{% block body %}
<h1>宏模板</h1>
{% macro input(name,value='',type='text') %}
<input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
{% endmacro %}
{% macro textarea(name,value='',rows=10,cols=40)%}
<textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols }}">{{ value|e }}</textarea>
{% endmacro %}
{% endblock %}
index.html文件中内容:
{% extends 'base.html' %}{#继承模板base.html#}
{% block title %}
张梦姣的首页
{% endblock %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static',filename='CSS/index.css') }}">{#加载静态文件#}
{% endblock %}
{% block body %}
<h1>我是首页</h1>
{% endblock %}
about.html文件中内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>关于我们</title>
</head>
<body>
<h1>我是{{ username }},长度为{{ username | length}}!!!</h1>{#过滤器|#}
<h2>{{ books|join('***') }}</h2>
{% if age>18 %}
<div>您已成年</div>
{% elif age==18 %}
<div>刚好成年</div>
{% else %}
<div>未成年</div>
{% endif %}
<ul>
{% for book in books %}
<li>{{ book }}</li>{#变量就用两个大括号#}
{% endfor %}
</ul>
{% for k,v in person.items() %}
<ul>{{ k }}:{{ v }}</ul>
{% endfor %}
{#测试器#}
{% if 'AsC' is upper %}{#'aBcD'是否全部是大写#}
<div>hahahha</div>
{% else %}
<div>heiheihei</div>
{% endif %}
{#宏macro:可以传递参数,但是不能有返回值#}{#
{% macro input(name,value='',type='text') %}
{{ name }}<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}">
{% endmacro %}
<p>{{ input('李玟琪') }}</p>
<p>{{ input('张梦姣',type="password") }}</p>#}
{#宏可以直接从自己写的文件"forms.html"中导入#}{#
{% import 'forms.html' as forms %}
<dl>
<dt>Username</dt>
<dd>{{ forms.input('username') }}</dd>
<dt>Password</dt>
<dd>{{ forms.input('password',type='password') }}</dd>
</dl>
<p>{{ forms.textarea('comment') }}</p>#}
{#赋值语句:set,可以赋值为任意类型#}
{% set zzu='郑州大学'%}
<div>我的学校是{{ zzu }}</div>
{#限制作用域with:将set语句放在其中,这样创建的变量只在with代码块中才有效#}
{% with %}
{% set a=[('index.html', 'Index'), ('about.html', 'About')] %}
{{ a }}
{% endwith %}
{#也可以在with的后面直接添加变量#}
{% with b='zmj' %}
<li>b</li>
{% endwith %}
{#自动转义逃脱#}
{% autoescape false %}{#关闭了自动转义#}
<p>autoescaping is disabled here</p>
<p>{{ will_not_be_escaped }}</p>
{% endautoescape %}
{#运算符:拼接多个字符串用波浪号~#}
<li>{{ "我爱你," ~ "我也爱你"}}</li>
<li>{{ "我爱你," + "我也爱你"}}</li>{#不建议#}
{#静态文件的加载:url_for('static',filename='xxx.css')#}
</body>
</html>
index.css文件中内容:
h1{
background-color: bisque;
}
第二章:蓝图
目录结构如下:
book.py文件中内容:
"""和图书有关的都写在book.py文件中"""
from flask import Blueprint#蓝图
from flask import render_template
#url_prefix:127.0.0.1:5000/book
bp=Blueprint('book',__name__,url_prefix="/book")
@bp.route('/list/')
def book_list():
return render_template('book_list.html')#渲染还是从templates文件夹中寻找
course.py文件中内容:
"""和课程相关的都写在course.py文件中"""
from flask import Blueprint
bp=Blueprint('course',__name__,url_prefix='/course')
@bp.route('/list/')
def course_list():
return "课程列表"
user.py文件中内容:
"""和用户相关的都放在user.py文件中"""
from flask import Blueprint
bp=Blueprint('user',__name__,url_prefix='/user')
@bp.route('/list/')
def user_list():
return "用户列表"
book_list.html文件中内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图书列表</title>
</head>
<body>
<h1>图书列表</h1>
<li>《水浒传》</li>
<li>《三国演义》</li>
<li>《西游记》</li>
<li>《红楼梦》</li>
</body>
</html>
app.py文件中内容:
from flask import Flask
from apps.book import bp as book_bp
from apps.course import bp as course_bp
from apps.user import bp as user_bp
app = Flask(__name__)
#绑定蓝图
app.register_blueprint(book_bp)
app.register_blueprint(course_bp)
app.register_blueprint(user_bp)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
第三章:SQLAlchemy
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import create_engine
app = Flask(__name__)
#数据库的配置变量
HOSTNAME='127.0.0.1'
PORT =3306
DATABASE='zl_flask'
USERNAME='root'
PASSWORD='abc123'
DB_URI='mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)
app.config['SQLALCHEMY_DATABASE_URI']=DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True#跟踪修改
db = SQLAlchemy(app)
class User(db.Model):
__tablename__='user'
id=db.Column(db.Integer,primary_key=True,autoincrement=True)
username=db.Column(db.String(200),nullable=False)
class UserExtension(db.Model):
__tablename__='user_extension'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
school=db.Column(db.String(100))
user_id=db.Column(db.Integer,db.ForeignKey('user.id'))
#db.backref
#1.作用:在反向传播的时候,如果需要传递一些其他的参数,那么就需要用到这个参数;否则不需要使用,只要在relationship的backref参数上设置反向名称就可以了
#2.uselist=False:代表反向引用时,不是一个列表,而是一个对象
user=db.relationship("User",backref=db.backref('extension',uselist=False))
#定义ORM模型
class Article(db.Model):
__tablename__='article'
id=db.Column(db.Integer,primary_key=True,auto_increment=True)
title=db.Column(db.String(200),nullable=False)
content=db.Column(db.Text,nullable=False)
author_id=db.Column(db.Integer,db.ForeignKey("user.id"))#外键:是属于数据库层面的,不推荐使用
#relationship:
#1.第一个参数是模型的名字,必须要和模型名字保持一致
#2.第二个参数代表反向引用,代表对方访问我的时候的字段名称
#3.前提是已经绑定了外键
author=db.relationship("User",backref='articles')#一对多的关系,一个作者可以写很多文章,所以article+s
#暂时还没有涉及到ORM迁移数据库的版本管理,所以现在只能先删除所有表,再创建
db.drop_all()
db.create_all()
@app.route('/otm')#one to many一对多
def one_to_many():
article1=Article(title='111',content='xxx')
article2=Article(title='222',content='yyy')
user=User(username='张梦姣')
article1.author=user
article2.author=user
db.session.add(article1)
db.session.add(article2)
db.session.commit()
return'one to many数据操作成功'
@app.route('/oto')#one_to_one一对一
def one_to_one():
user=User(username='李玟琪')
extension=UserExtension(school='清华大学')
user.extension=extension
db.session.add(user)
db.session.commit()
@app.route('/')
def hello_world():
#写一个测试代码来验证数据库是否连接成功
engine=db.get_engine()
conn=engine.connect()
result=conn.execute('select 1')
print(result.fetchone())
conn.close()
return 'Hello World! ZMJ'
@app.route('/article')
def article_view():
#1.添加数据
article=Article(title='钢铁是怎样炼成的',content='xxx')
db.session.add(article)
#提交
db.session.commit()
#2.查询数据
#filter_by:返回一个类列表的的对象
article =Article.query.filter_by(id=1)[0]
print(article.title)
#3.修改数据
article.content='yyy'
db.session.commit()
#4.删除数据
Article.query.filter_by(id=1)[0].delete()
db.session.commit()
return '数据操作成功'
if __name__ == '__main__':
app.run()