ORM用类来定义表,类的实例化代表了表的一整行,那么整个表就是类的实例化的LIST.
二、在表单中实现增删改查代码样例 增@app.route('/new', methods=['GET', 'POST'])
def new_note():#是一个比较典范的程序
form = NewNoteForm()
if form.validate_on_submit():
body = form.body.data
note = Note(body=body)
db.session.add(note)
db.session.commit()
flash('Your note is saved.')
return redirect(url_for('index'))
return render_template('new_note.html', form=form)
删(里面包括了用主键查表的行)
@app.route('/delete/', methods=['POST'])
def delete_note(note_id):
form = DeleteNoteForm()
if form.validate_on_submit():
note = Note.query.get(note_id)#通过id先找到
db.session.delete(note)#然后直接删除掉
db.session.commit()
flash('Your note is deleted.')
else:
abort(400)
return redirect(url_for('index'))
改(直接覆盖掉就行了)
@app.route('/edit/', methods=['GET', 'POST'])
def edit_note(note_id):
form = EditNoteForm()
note = Note.query.get(note_id)
if form.validate_on_submit():
note.body = form.body.data
db.session.commit()
flash('Your note is updated.')
return redirect(url_for('index'))
form.body.data = note.body # preset form input's value
return render_template('edit_note.html', form=form)
查
note = Note.query.get(note_id)#查一行 notes = Note.query.all()#查全部三、表关系 一对多
# one to many
class Author(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(20), unique=True)
phone = db.Column(db.String(20))
articles = db.relationship('Article') # collection,这是一个集合关系属性,里面包含了作者的所有文章
def __repr__(self):
return '' % self.name
#最后有两种方法来建立:
#第一种是“多”这一端,直接给外键赋值
#第二种是“一”这一端,将关系属性赋值给实际对象
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(50), index=True)
body = db.Column(db.Text)
author_id = db.Column(db.Integer, db.ForeignKey('author.id'))#用外键实现一对多的关系
def __repr__(self):
return '' % self.title
一对一
# one to one
#一对一就是一种特殊的一对多,只不过那个list里的元素变成一个了而已
class Country(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30), unique=True)
capital = db.relationship('Capital', back_populates='country', uselist=False) # collection -> scalar
def __repr__(self):
return '' % self.name
class Capital(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30), unique=True)
country_id = db.Column(db.Integer, db.ForeignKey('country.id'))
country = db.relationship('Country', back_populates='capital') # scalar
def __repr__(self):
return '' % self.name
多对多
借助关联表作为跳板,一方先对关联表进行检索,然后找到对应的另一方信息。
# many to many with association table
association_table = db.Table('association',
db.Column('student_id', db.Integer, db.ForeignKey('student.id')),
db.Column('teacher_id', db.Integer, db.ForeignKey('teacher.id'))
)
class Student(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(70), unique=True)
grade = db.Column(db.String(20))
teachers = db.relationship('Teacher',
secondary=association_table,
back_populates='students') # collection
def __repr__(self):
return '' % self.name
class Teacher(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(70), unique=True)
office = db.Column(db.String(20))
students = db.relationship('Student',
secondary=association_table,
back_populates='teachers') # collection
def __repr__(self):
return '' % self.name
三、总代码及注释
import os
import sys
import click
from flask import Flask
from flask import redirect, url_for, abort, render_template, flash
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import SubmitField, textareaField
from wtforms.validators import DataRequired
# SQLite URI compatible
WIN = sys.platform.startswith('win')
if WIN:
prefix = 'sqlite:///'
else:
prefix = 'sqlite:'
app = Flask(__name__)
app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = True
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'secret string')
#配置数据库URI
app.config['SQLALCHEMY_DATAbase_URI'] = os.getenv('DATAbase_URL', prefix + os.path.join(app.root_path, 'data.db'))
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app) #实例化一个SQLAlchemy,命名为db
# handlers
@app.shell_context_processor
def make_shell_context():
return dict(db=db, Note=Note, Author=Author, Article=Article, Writer=Writer, Book=Book,
Singer=Singer, Song=Song, Citizen=Citizen, City=City, Capital=Capital,
Country=Country, Teacher=Teacher, Student=Student, Post=Post, Comment=Comment, Draft=Draft)
@app.cli.command()
@click.option('--drop', is_flag=True, help='Create after drop.')
def initdb(drop):
"""Initialize the database."""
if drop:
db.drop_all()
db.create_all()
click.echo('Initialized database.')
# Forms
#创建三个表单,分别用于填写新笔记、编辑笔记和删除笔记
class NewNoteForm(FlaskForm):
body = textareaField('Body', validators=[DataRequired()])
submit = SubmitField('Save')
class EditNoteForm(FlaskForm):
body = textareaField('Body', validators=[DataRequired()])
submit = SubmitField('Update')
class DeleteNoteForm(FlaskForm):
submit = SubmitField('Delete')
# Models
class Note(db.Model): #定义了一个Note类,即后面要实例化的笔记本的行,这里包含一个id作为主键,还有一个文本内容
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.Text)
# optional
def __repr__(self):
return '' % self.body
@app.route('/')
def index():
form = DeleteNoteForm()
notes = Note.query.all()
return render_template('index.html', notes=notes, form=form)
@app.route('/new', methods=['GET', 'POST'])
def new_note():#是一个比较典范的程序
form = NewNoteForm()
if form.validate_on_submit():
body = form.body.data
note = Note(body=body)
db.session.add(note)
db.session.commit()
flash('Your note is saved.')
return redirect(url_for('index'))
return render_template('new_note.html', form=form)
@app.route('/edit/', methods=['GET', 'POST'])
def edit_note(note_id):
form = EditNoteForm()
note = Note.query.get(note_id)
if form.validate_on_submit():
note.body = form.body.data
db.session.commit()
flash('Your note is updated.')
return redirect(url_for('index'))
form.body.data = note.body # preset form input's value
return render_template('edit_note.html', form=form)
@app.route('/delete/', methods=['POST'])
def delete_note(note_id):
form = DeleteNoteForm()
if form.validate_on_submit():
note = Note.query.get(note_id)#通过id先找到
db.session.delete(note)#然后直接删除掉
db.session.commit()
flash('Your note is deleted.')
else:
abort(400)
return redirect(url_for('index'))
# one to many
class Author(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(20), unique=True)
phone = db.Column(db.String(20))
articles = db.relationship('Article') # collection,这是一个集合关系属性,里面包含了作者的所有文章
def __repr__(self):
return '' % self.name
#最后有两种方法来建立:
#第一种是“多”这一端,直接给外键赋值
#第二种是“一”这一端,将关系属性赋值给实际对象
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(50), index=True)
body = db.Column(db.Text)
author_id = db.Column(db.Integer, db.ForeignKey('author.id'))#用外键实现一对多的关系
def __repr__(self):
return '' % self.title
# many to one
class Citizen(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(70), unique=True)
city_id = db.Column(db.Integer, db.ForeignKey('city.id'))
city = db.relationship('City') # scalar
def __repr__(self):
return '' % self.name
class City(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30), unique=True)
def __repr__(self):
return '' % self.name
# one to one
#一对一就是一种特殊的一对多,只不过那个list里的元素变成一个了而已
class Country(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30), unique=True)
capital = db.relationship('Capital', back_populates='country', uselist=False) # collection -> scalar
def __repr__(self):
return '' % self.name
class Capital(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30), unique=True)
country_id = db.Column(db.Integer, db.ForeignKey('country.id'))
country = db.relationship('Country', back_populates='capital') # scalar
def __repr__(self):
return '' % self.name
# many to many with association table
association_table = db.Table('association',
db.Column('student_id', db.Integer, db.ForeignKey('student.id')),
db.Column('teacher_id', db.Integer, db.ForeignKey('teacher.id'))
)
class Student(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(70), unique=True)
grade = db.Column(db.String(20))
teachers = db.relationship('Teacher',
secondary=association_table,
back_populates='students') # collection
def __repr__(self):
return '' % self.name
class Teacher(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(70), unique=True)
office = db.Column(db.String(20))
students = db.relationship('Student',
secondary=association_table,
back_populates='teachers') # collection
def __repr__(self):
return '' % self.name
# one to many + bidirectional relationship
class Writer(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
books = db.relationship('Book', back_populates='writer')
def __repr__(self):
return '' % self.name
class Book(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), index=True)
writer_id = db.Column(db.Integer, db.ForeignKey('writer.id'))
writer = db.relationship('Writer', back_populates='books')
def __repr__(self):
return '' % self.name
# one to many + bidirectional relationship + use backref to declare bidirectional relationship
class Singer(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(70), unique=True)
songs = db.relationship('Song', backref='singer')
def __repr__(self):
return '' % self.name
class Song(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), index=True)
singer_id = db.Column(db.Integer, db.ForeignKey('singer.id'))
def __repr__(self):
return '' % self.name
# cascade
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(50))
body = db.Column(db.Text)
comments = db.relationship('Comment', back_populates='post', cascade='all, delete-orphan') # collection
class Comment(db.Model):
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.Text)
post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
post = db.relationship('Post', back_populates='comments') # scalar
# event listening
class Draft(db.Model):
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.Text)
edit_time = db.Column(db.Integer, default=0)
@db.event.listens_for(Draft.body, 'set')
def increment_edit_time(target, value, oldvalue, initiator):
if target.edit_time is not None:
target.edit_time += 1
# same with:
# @db.event.listens_for(Draft.body, 'set', named=True)
# def increment_edit_time(**kwargs):
# if kwargs['target'].edit_time is not None:
# kwargs['target'].edit_time += 1



