在其他的文章裡,我寫了 Flask 對資料庫進行增刪改查的方法,也寫了 Flask 將資料返回給前端的方法。
這篇文章,將兩者串聯起來,實現從前端到資料庫的整個過程,通過前端頁面查詢資料庫的資料,從前端向資料庫新增資料。
一、建立資料庫並新增資料
在專案資料夾下建立一個 search_and_add.py 檔案,在裡面編寫建立資料表和新增資料的程式碼。
from flask import Flaskfrom flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://admin:[email protected]:3306/MyDB_one'app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Trueapp.config['SQLALCHEMY_ECHO'] = Truedb = SQLAlchemy(app)class Phone(db.Model): __tablename__ = 'Phone_tb' pid = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(32)) person_id = db.Column(db.Integer, db.ForeignKey('Person_tb.mid')) def __repr__(self): return 'Phone_name: {}'.format(self.name)class Person(db.Model): __tablename__ = 'Person_tb' mid = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) age = db.Column(db.Integer) phones = db.relationship('Phone', backref='person', lazy='dynamic') def __repr__(self): return 'Person_name: {}'.format(self.name)db.drop_all()db.create_all()if __name__ == '__main__': per_one = Person(name='You', age=18) per_two = Person(name='Me', age=81) per_three = Person(name='JackMa', age=60) per_four = Person(name='Panshiyi', age=50) per_five = Person(name='DingLei', age=40) db.session.add_all([per_one, per_two, per_three, per_four, per_five]) phone_one = Phone(name='IPhone', person_id=1) phone_two = Phone(name='Mi', person_id=3) phone_three = Phone(name='NOKIA', person_id=2) phone_four = Phone(name='HUAWEI', person_id=4) phone_five = Phone(name='OPPO', person_id=5) phone_six = Phone(name='VIVO', person_id=1) db.session.add_all([phone_one, phone_two, phone_three, phone_four, phone_five, phone_six]) db.session.commit() app.run(debug=True)
程式碼中使用提前建立好的資料庫使用者 admin 和提前建立好的資料庫 MyDB_one ,連線資料庫、建立資料表並在資料表中新增資料。
執行程式碼後,會在資料庫 MyDB_one 中(先刪除再)建立兩張表 Person_tb 和 Phone_tb ,並分別在兩張表中新增5條和6條資料。
新增完初始資料後,將 db.drop_all() ,db.create_all() 和新增資料的程式碼註釋掉,避免重複建立和新增。
二、前端頁面準備
在模板檔案目錄 templates 中建立一個 serach_and_add.html 前端模板檔案,然後在裡面編寫前端頁面的程式碼。
這篇文章的主要目的研究後端的介面實現,模板檔案只是準備工作,所以只寫了幾個標籤。
需要的功能是預設情況下首頁展示全部資料,查詢時只顯示查詢的資料,新增後顯示新增後所有的資料。(本來打算寫一個樣式更好點的前端頁面,查詢資料和新增資料時在彈框操作。功能實現了,但是寫得太臭,所以乾脆不寫樣式了,以後再把前端寫好點。)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Person</title></head><body><form method="post"> <label>人名:</label> <input id="person" name="person" type="text" value=""><br/> <label>手機:</label> <input id="phone" name="phone" type="text" value=""><br/><br/> <input id="search" name="search" type="submit" value="查詢"> <input id="add" name="add" type="submit" value="新增"><br/></form><ul> {% for person in persons %} <li>{{ person.name }}</li> <ul> {% for phone in person.phones %} <li>{{ phone.name }}</li> {% else %} <li>無</li> {% endfor %} </ul> {% endfor %}</ul></body></html>
三、實現查詢所有資料的功能
訪問前端首頁時,預設查詢出所有 person 和對應的 phone 。
from flask import [email protected]('/')def index(): persons = Person.query.all() return render_template('search_and_add.html', persons=persons)
在 search_and_add.py 中建立模型類的後面新增上面的檢視函式,查詢出 Person 模型類中的所有資料,返回給前端。
因為 Person 和 Phone 是有關係欄位的,Person 對 Phone 是一對多的關係,所以通過 Person 中的關係欄位可以獲取到對應的 Phone 。
執行 search_and_add.py ,訪問 http://127.0.0.1:5000/ ,顯示效果如下:
四、實現查詢部分資料的功能
上面的檢視函式預設會查詢所有的資料進行展示,現在實現輸入人名來查詢單條資料。
from flask import render_template, [email protected]('/', methods=['GET', 'POST'])def index(): persons = Person.query.all() if request.method == 'POST': person_name = request.form.get('person') persons = Person.query.filter_by(name=person_name) return render_template('search_and_add.html', persons=persons)
從 Flask 中匯入請求上下文 request ,後端通過請求上下文 request 獲取前端傳入的資料。前端要向後端傳遞資料,所以請求方式是 POST ,需要修改檢視函式支援的請求方式,通過 route 裝飾器中的 methods 來設定支援的請求方式。
將檢視函式修改成上面的程式碼,重新執行 search_and_add.py ,訪問 http://127.0.0.1:5000/ ,在人名的輸入框中輸入需要查詢的人名,如 You ,然後點選“查詢”按鈕,執行結果如下:
如果查詢的資料不存在,則顯示內容為空。
五、實現新增資料的功能
前面是查詢資料庫中的資料展示在前端頁面,現在實現新增資料到後端資料庫,並將所有資料一起展示在前端。
from flask import render_template, request, redirect, flashimport [email protected]('/', methods=['GET', 'POST'])def index(): if request.method == 'GET': persons = Person.query.all() return render_template('search_and_add.html', persons=persons) if request.method == 'POST': person_name = request.form.get('person') if not person_name: return redirect('/') submit = request.form.get('search') if submit == '查詢': persons = Person.query.filter_by(name=person_name) return render_template('search_and_add.html', persons=persons) submit = request.form.get('add') if submit == '新增': phone_name = request.form.get('phone') person = Person.query.filter_by(name=person_name).first() if person: if not phone_name: return redirect('/') phone = Phone.query.filter(Phone.name == phone_name, Phone.person_id == person.mid).first() if phone: flash('資料已存在!') else: phone = Phone(name=phone_name, person_id=person.mid) add_data(phone) else: person = Person(name=person_name, age=random.randint(18, 25)) add_data(person) if not phone_name: return redirect('/') phone = Phone(name=phone_name) phone.person = person add_data(phone) return redirect('/')def add_data(obj): try: db.session.add(obj) db.session.commit() except Exception as e: print(e) db.session.rollback() flash("新增失敗")
從 Flask 中匯入了 redirect 方法用於重定向,因為我們新增資料後要把資料全部展示在首頁,所以重定向到首頁。
匯入 flash 方法用於向前端傳送提示資訊,為了使用 flash ,需要給 app 增加 SECRET_KEY 配置,這個祕鑰是一串任意字串。
app.config['SECRET_KEY'] = 'NFAIOSDFHASOGHAOSPIGAOWE'
並且,要在前端獲取 flash 傳送的提示資訊,需要使用 get_flashed_messages() 方法進行接收,然後將接收到的資訊進行展示,所以在模板檔案中新增如下程式碼。
{% for message in get_flashed_messages() %} {{ message }}{% endfor %}
修改程式碼後,重新執行 search_and_add.py ,訪問 http://127.0.0.1:5000/ ,在人名和手機的輸入框中輸入需要新增的人名和手機,如 Tayer,IPhone,然後點選“新增”按鈕,執行結果如下:
當然,上面的程式碼中實現了每種情況的新增,如只新增人名不新增手機,新增的人名和手機已存在等,這些都已經包含在上面的程式碼中了,就不一一演示了。