1. 程式人生 > >python就業班第32天----flask程式碼複用、資料庫

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執行結果:

插入圖jybday32-1

包含:將一個檔案的內容完整拷貝到另外一個檔案中

<!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 插入圖jybday32-3

CSRF

CSRF:跨站請求偽造 聽的時候睡著了,以後再補回來

flask中資料庫

資料庫:ORM模型 對資料庫的操作都轉化為對類、屬性、方法的操作 好處:

  • 1.不用編寫各種資料庫的sql語句
  • 2.不在關注,使用的是mysql、oracle等資料庫

模型類對映成資料庫表:

  • 類名稱–>資料庫表名 要想自定義的話,設定__tablename__屬性就可以了
  • 類屬性–>資料庫欄位
  • 類的物件–>資料庫每一行資料

通過SQLAlchemy(ORM)操作資料庫的流程

  • 1.安裝擴充套件包 pip install flask sqlalchemy

    1. 安裝資料庫驅動 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中方式]:
  1. User.query.filter(User.id==4)
  2. users = User.query.filter(User.id==4).all() users.first()
  3. 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的[兩種方式]:
  1. User.query.filter(User.name!='wang').all()
  2. User.query.filter(not_(User.name=='wang')).all()
  • 查詢名字和郵箱都以li開頭的資料:
  1. User.query.filter(User.name.startswith('li'),User.query.email.startswith('li')).all()
  2. 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 * 敲上面的查詢操作

插入圖jybday32-4