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.關於檢視函式。(待續)