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.关于视图函数。(待续)

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