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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章