1. 程式人生 > >ALchemy學習-從mysql資料庫讀取資料顯示到頁面

ALchemy學習-從mysql資料庫讀取資料顯示到頁面

在python中,一般不會在資料庫裡寫SQL語句,而是通過ORM(物件關係對映)將python物件對映為資料庫裡的資料,實現對資料庫的操作。ALchemy是python裡功能強大的一款OMR包。

我寫了一個簡單的程式是這樣的:
1. http://localhost:3000/ 頁面可以訪問並且返回預期的頁面內容,頁面內容需要包含文章標題列表及文章連結地址
2.文章內容可以通過 http://localhost:3000/ 頁面中的連結地址可以訪問
執行環境:python+mysql+Alchemy+flask。

第一步我要在我的app.py(程式名)裡建立相應的對映類File和Category。實現如下,重點說明一下我在實現過程遇到的問題。

1.config引數設定:
TEMPLATES_AUTO_RELODE這個引數設定為true,這樣每次app.py被修改後模板都會自動載入;
SQLALCHEMY_TRACK_MODIFICATIONS這個引數一定要設定,true和false都可以,如果不設定會報錯。
SQLALCHEMY_DATABASE_URI這個引數就是告訴app.py連結哪裡的資料庫。
引數格式是這樣的:

mysqldb://<username>:<password>@<host>:3306/<database>,其中3306是mysql的預設埠號)

2.有的資料是下面這樣的寫法,但是我用的時候報錯了,說是無法找到SQLAlchemy。後面我查了原因,正確的寫法應該是程式碼片貼出來的那種。

from flask.ext.sqlalchemy import SQLAlchemy
from flask import Flask,render_template, abort
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime


app = Flask(__name__)
app.config['TEMPLATES_AUTO_RELODE']=True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_DATABASE_URI'
] = 'mysql://root:@localhost/blog' db = SQLAlchemy(app) class Category(db.Model): id = db.Column(db.Integer,primary_key = True) name = db.Column(db.String(80)) def __init__(self,name): self.name = name def __repr__(self): return '<user %r>' % self.name class File(db.Model): id = db.Column(db.Integer,primary_key = True) title = db.Column(db.String(255)) created_time = db.Column(db.DateTime) content = db.Column(db.Text) categery_id = db.Column(db.Integer,db.ForeignKey('category.id')) category = db.relationship('Category',backref=db.backref('files',lazy='dynamic')) def __init__(self,title,created_time,content,category): self.title = title self.created_time = created_time self.content = content self.category = category def __repr__(self): return '<user %r>' % self.title all_file = File.query.all() print(all_file) #index頁面,用來顯示文章標題列表 @app.route('/') def index(): return render_template('index.html',all_file = all_file) @app.route('/files/<file_id>') def file(file_id): f = File.query.filter_by(id=file_id).first() if f: return render_template('file.html', file=f) abort(404) ''' is_found = 0 for fil in all_file: #print(file_id) if file_id == fil.id: is_found = 1 return render_template('file.html',file = fil) if is_found == 0: abort(404) ''' #file頁面,顯示文章內容、建立時間以及文章類別 @app.errorhandler(404) def not_found(error): return render_template('404.html'),404

3.插入資料。

from app import db,Category,File
from datetime import datetime

db.create_all()

java=Category('Java')
python=Category('Python')
file1=File('Hello,Java',datetime.utcnow(),'File Content - Java is cool',java)
file2=File('Hello,Python',datetime.utcnow(),'File Content - Python is cool',python)

db.session.add(java)
db.session.add(python)
db.session.add(file1)
db.session.add(file2)

db.session.commit()
<!-- index頁面 -->
{% for file in all_file %}
    <a href = 'http://localhost/3000/files/{{file.id}}'><p>{{file.title}}</p></a>
{% endfor %}

<!-- file頁面 -->
<p>content:{{ file.content }}</p>
<p>created_time:{{ file.created_time }}</p>
<p>category:{{ file.category.name }}</p>

<!-- 404頁面 -->
<p>400:not found </p>

寫好對映類後為資料庫新增記錄的時候出現了很多錯誤。
第一種錯誤是資料型別對不上。在往資料庫新增資料的時候,欄位順序要和init函式引數順序一致。
比如說File對映類的int函式是這樣的:def __init__(self,title,created_time,content,category): 那麼插入資料的時候就得這麼寫:file1=File('Hello,Java',datetime.utcnow(),'File Content - Java is cool',java)

第二種錯誤是因為當時對relationship()這個函式以及它的backref引數的用法不熟悉。上面的對映類File和Category對映到mysql資料庫就是file和category兩個表。它們之間是多對一的關係,每篇文章只有一個類別,一個類別可以對應多篇文章。所以file裡的category_id是外來鍵,關聯到category表的主鍵。為了表現這種關係,我在File對映類裡添加了category,並用relationship將他們聯絡起來。

剛開始的時候,我是這樣理解的:既然它們是通過外來鍵關聯的,對映類File裡的categery_id就是Category對映類的id,那在插入資料的時候肯定要把category的id也寫在file裡。所以剛開始File的init函式我是這樣寫的:def __init__(self,title,created_time,content,category_id):,然後插入資料:file1=File('Hello,Java',datetime.utcnow(),'File Content - Java is cool',java.id) 接著我在資料庫裡檢視file表的資料:
這裡寫圖片描述

可以看到我預想中的category_id的值是空的,它的值沒有被傳進來。而且這樣寫我無法通過file的category_id訪問到category裡的name。
這裡寫圖片描述

這時候我才意識到在init函式裡我應該把傳入category這個引數並設定反引用引數,才能實現file和category兩個表資料的關聯查詢。
這裡寫圖片描述

這裡寫圖片描述

4.關於檢視函式。(待續)