python就業班第32天----flask程式碼複用、資料庫
程式碼複用
flask中程式碼複用:
- 1.巨集(macro)
定義巨集:
{% macro 巨集名(形參=預設值1, ...) %}
html程式碼
{% endmacro %}
使用當前檔案巨集:{{ 巨集名(形參=值1,...) }}
- 2.繼承(extends)
使用當前檔案巨集:{% 巨集名(引數) %}
使用其它檔案巨集:{% import '巨集檔名' as 別名 %}
{% end import %}
- 3.包含(include)
{% include '檔名' %}
{% include '檔名' ignore missing %}
// 如果不存在,不會報錯
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
{# 定義巨集 #}
{% macro myinput(name,password) %}
<label>{{ name }}</label><input type="text" name="username"><br>
<label>{{ password }}</label><input type="password" name="password" >
{% endmacrop %}
{# 使用當前檔案巨集 #}
{{ myinput("賬號","密碼") }}
<br>
{# 使用其它檔案巨集 #}
{% import 'file02otherMacro.html' as other_macro %}
{{ other_macro.myinput('使用者名稱','密碼') }}
</body>
</html>
file02otherMacro.html裡面寫:
{% macro myinput(name,password) %}
<label>{{ name }}</ label><input type="text" name="username">
<br>
<label>{{ password }}</label><input type="password" name="password">
<% endmacro %>
繼承:共性抽取,程式碼複用
格式:{% extends '父檔名' %}
父類表現:
- 1.所有子類都有的內容,直接在父類寫死
- 2.有些子類有,有些子類沒有,定義程式碼塊,如果子類需要不重寫,如果不需要就重寫
- 3.所有子類都不相同
子類表現:
- 1.extends繼承diamante建議寫在子類檔案第一行,所有內容都繼承過來
- 2.根據需要,有選擇性的重寫父類中的block內容
- 3.如果重寫block父類內容,還要用父類的,使用super()
父類file05fu.html程式碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>父類標題部分</h1>
{# 分類資訊 #}
{% block category %}
<a herf="#">新聞</a>
<a href="#">娛樂</a>
<a href="#">體育</a>
{% endblock %}
{# 中間正文部分 #}
{% block content %}
{% endblock %}
<h1>父類底部部分</h1>
</body>
</html>
子類file03zi.html:
{# 繼承 #}
{% extends 'file05fu.html' %}
{# 重寫父類,content內容 #}
{% block content %}
<h1>file03的正文部分</h1>
{% endblock %}
{% block category %}
{# 呼叫父類的category #}
{{ super() }}
{# 新增八卦 #}
<a href="#">八卦</a>
{% endblock %}
子類file03zi.html執行結果:
包含:將一個檔案的內容完整拷貝到另外一個檔案中
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{# 不存在 #}
{% include 'file04zizizi.html' ignore missing %}
{# 將file05fu.html內容拿過來直接渲染 #}
{% include 'file05fu.html' %}
</body>
</html>
ignore missing:如果不存在,也不報錯 執行結果和父類file05fu.html
jinja模板(指html中)中特有變數和函式 特點:不需要從flask程式裡面,傳遞到模板,就可以直接使用的 特殊的變數和函式有(寫在html{{}}裡面):
- config:app的配置物件,和flask裡面的app.config是一回事
- request:請求物件
- g:應用上下文物件
- url_for():通過函式名,解析到所對應的路徑
- get_flashed_message():消耗flash()(寫在py檔案裡面)方法裡面儲存的資訊(一把全消耗完)
flash:儲存區訊息使用flash('訊息')
,儲存完了之後使用get_flashed_message()消耗掉
使用之前需要匯入:from flask import flash
還需要配置session祕鑰
app.config['SECRET_KEY'] = 'asdqwesdf'
from flask import Flask,flash,g,render_template
app =Flask(__name__)
app.config["SECRET_KEY"] = "HELLOWORLD"
@app.route("/hello")
def hello_world():
g.name = 'laowang'
flash("登陸成功")
return render_template("file07special_variable.html")
@app.route("/test/<int:token>")
def test(token):
flash("登入失敗")
return 'test'
if __name__ == "__main__":
app.run(debug=True)
file07的special_variable.html裡面寫:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>config配置物件:{{config}}</h2>
<h2>request請求引數:{{request.args}}</h2>
<h2>request請求方式:{{request.methods}}</h2>
<h2>g物件:{{g.name}}</h2>
<h2>url_for()方法:{{url_for('hello_world')}}</h2>
<h2>url_for()方法:{{url_for('test',token=199)}}</h2>
<hr>
{% for message in get_flashed_messages() %}
<h3>{{ message }}</h3>
{% endfor %}
</body>
</html>
先訪問一次test
在訪問hello
CSRF
CSRF:跨站請求偽造 聽的時候睡著了,以後再補回來
flask中資料庫
資料庫:ORM模型 對資料庫的操作都轉化為對類、屬性、方法的操作 好處:
- 1.不用編寫各種資料庫的sql語句
- 2.不在關注,使用的是mysql、oracle等資料庫
模型類對映成資料庫表:
- 類名稱–>資料庫表名
要想自定義的話,設定
__tablename__
屬性就可以了 - 類屬性–>資料庫欄位
- 類的物件–>資料庫每一行資料
通過SQLAlchemy(ORM)操作資料庫的流程
-
1.安裝擴充套件包
pip install flask sqlalchemy
-
- 安裝資料庫驅動
pip install mysqldb / pymysql
(pymysql不相容,可能裝不上)
- 安裝資料庫驅動
-
3.匯入SQLAlchemy類
from flask_sqlalchemy import SQLAlchemy
-
4.配置資料庫連線資訊(設定config字典)
app.config[' '] = " "
-
5.建立SQLAlchemy()物件 (物件名db),關聯app
db =SQLAlchemy(app)
-
6.編寫模型類,繼承自db.Model(建立表)
class Role(db.Model):
-
7.編寫屬性,==db.Colomn(型別,約束資訊)==表示一列
id = db.Column(db.Integer, primary_key=Trye, auto_increment=True)
// 整型,主鍵,自增長 注意:Integer不要寫錯name = db.Column(db.String(64), unique=True)
// 字串型別,不允許重複 -
8.操作(資料庫的增刪改查)
魔法方法:__ repr__:
如果繼承自object的類,使用__str__
可以方便的查詢物件的輸出內容
如果繼承自db.Model類,使用__repr__
可以方便的查詢物件的輸出內容
增刪改操作:
-
建立物件:
us1 = User(name="wang" , email="[email protected]" , password="123456" , role_id=ro1.id)
ro1 = Role(id=1,name='admin')
-
db.create_all()
建立索引繼承自db.Model的類 -
db.drop_all()
刪除所有繼承自db.Model的類 -
db.session.add(obj)
新增物件 -
db.session.add_all( [ obj1 , obj2 ] )
新增多個物件 -
db.session.delete(obj)
刪除物件 -
db.session.commit()
提交回話 -
db.session.rollback()
回滾 -
db.session.remove()
移除會話
注意點:
- 1.ORM不能建立資料庫,只能穿件資料庫的表(要手動去建立資料庫)
- 2.預設情況下,生成的表名稱是類名稱的小寫形式,如果需要指定,設定
__tablename__
- 3.
<協議名稱>://<使用者名稱>:<密碼>@<ip地址>:<埠>/<資料庫名>
如果安裝的是mysqldb驅動,連線資料庫協議:app.config['SQLALCHEMY_DATABASE_URI'] = " mysql://root:[email protected]:3306/basic12"
查詢操作:模型類.query()
注:下面的User是python中類名稱(繼承了db.Model的類),對應資料庫中表格
- 1.
User.query
拿到的是資料庫中user這個表所有的查詢結果集 - 2.先呼叫查詢過濾器
- 3.在呼叫查詢執行器
操作:
- 查詢所有使用者資料:
User.query.all()
返回的是個列表 - 查詢有多少個使用者:
User.query.count()
返回字串 - 查詢第一個使用者:
User.query.first()
返回物件 - 查詢id為4的使用者[3中方式]:
User.query.filter(User.id==4)
users = User.query.filter(User.id==4).all()
users.first()
User.query.filter_by(User.id=4).first().
- 查詢第4條資料:
User.query.get(4)
- 查詢名字結尾字元為g的所有資料[開始/包含]:
User.query.filter(User.name.endswith('g').all())
- 查詢名字開始字元為h的所有資料[開始/包含]:
User.query.filter(User.name.startswith('h').all())
- 查詢名字不等於wang的[兩種方式]:
User.query.filter(User.name!='wang').all()
User.query.filter(not_(User.name=='wang')).all()
- 查詢名字和郵箱都以li開頭的資料:
User.query.filter(User.name.startswith('li'),User.query.email.startswith('li')).all()
from sqlalchemy import and_
User.query.filter(and_(User.name.startswith('li'),User.query.email.startswith(li))).all()
- 查詢password是123456或email以itheima.com結尾的所有資料:匯入or_就好,略
- 查詢id為[1,3,5,7,9]的使用者列表:
User.query.filter(User.id.in ([1,3,5,7,9])).all()
- 查詢name為liu的角色資料:
user = User.query.filter(User.name=='liu').first()
user
role = Role.query.get(user.role_id)
role
- 查詢所有使用者資料,並以郵箱排序:
User.query.order_by(User.email).all()
- 降序:
User.query.order_by(User.email.desc()).all()
- 每頁3個,查詢第2頁的資料:
paginate = User.query.paginate(page,per_Page,Error_out)
引數1:page,要查詢哪一頁 引數2:per_page,每頁有幾條資料 引數3:Error_out,查不到會不會報錯
demo08database_query裡面寫
from flask import Flask
from flask_sqlalcheny import SQLAlchemy
app = Flask(__name__)
# 指定資料庫的連結資訊
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:[email protected]:3306/basic12"
#這個配置將來會被禁用,設定為True或者False可以解除警告資訊,建議設定False
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db.SQLAlchemy(app)
# 角色模型類(一方)
class Role(db.Model):
__tablename__ = "roles"
# db.Column() 表示模型類的屬性
# 主鍵
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(64),unique=True)
def __repr__(self):
return "<Role:%s,%s>"%(self.id,self.name)
# 使用者模型類(多方)
class User(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(64),unique=True)
email = db.Column(db.String(64),unique=True)
password = db.Column(db.String(64),unique=True)
# 外來鍵,關聯的是Role表中的主鍵id
role_id = db.Column(db.Integer,db.ForeignKey(User.id))
def __repr__(self):
return "<Users:%s,%s,%s,%s>"%(self.id,self.name,self.email,self.password)
if __name__ == "__main__":
# 為了演示方便,先刪除資料庫表,和模型類關聯的表
db.drop_all()
# 建立表,所有繼承自db.Model的表
db.create_all()
# 建立測試資料
ro1 = Role(name="admin")
db.session.add(ro1)
db.session.commit()
ro2 = Role(name="user")
db.session.add(ro2)
db.session.commit()
# 多條使用者資料
us1 = User(name='wang', email='[email protected]', password='123456', role_id=ro1.id)
us2 = User(name='zhang', email='[email protected]', password='201512', role_id=ro2.id)
us3 = User(name='chen', email='[email protected]', password='987654', role_id=ro2.id)
us4 = User(name='zhou', email='[email protected]', password='456789', role_id=ro1.id)
us5 = User(name='tang', email='[email protected]', password='158104', role_id=ro2.id)
us6 = User(name='wu', email='[email protected]', password='5623514', role_id=ro2.id)
us7 = User(name='qian', email='[email protected]', password='1543567', role_id=ro1.id)
us8 = User(name='liu', email='[email protected]', password='867322', role_id=ro1.id)
us9 = User(name='li', email='[email protected]', password='4526342', role_id=ro2.id)
us10 = User(name='sun', email='[email protected]', password='235523', role_id=ro2.id)
db.session.add_all([us1, us2, us3, us4, us5, us6, us7, us8, us9, us10])
db.session.commit()
app.run(debug=True)
然後在Pycharm裡開啟終端:
from demo08database_query import *
敲上面的查詢操作