flask_十二、模板视图渲染+一对多关系简述

模板视图渲染+一对多关系简述

一、模板视图渲染

1.1template下新建new_note.html

 

{% extends 'base.html'%}
{% from 'macros.html' import form_field %}
{% block content %}
<h2>New Note</h2>>
<form method="post">
    {{ form.csrf_token }}


    {{ form_field(form.body,rows=5,cols=50)}}
    {{ form.submit }}
</form>
{% endblock %}

 

1.2template下新建index.html

 

{% extends 'base.html'%}

{% block content %}
    <h1>Notebook</h1>
    <a href="{{ url_for ('new_note')}}">New Note</a>
    <h4>{{ notes|length }} notes:</h4>
    {% for note in notes %}
        <div class="note">
            <p>{{ note.body}}</p>
            <a class="btn" href="{{ url_for('edit_note',note_id=note.id) }}">Edit</a>
            <form method="post" action="{{ url_for('delete_note',note_id=note.id) }}">
                {{ form_delete.csrf_token }}
                {{ form_delete.submit(class='btn') }}
            </form>
        </div>
    {% endfor %}
{% endblock %}

 

1.3template下新增edit_note.html

 

{% extends 'base.html'%}
{% from 'macros.html' import form_field %}
{% block title %}Edit Note{% endblock %}

{% block content %}
<h2>Edit Note</h2>>
<form method="post">
    {{ form.csrf_token}}
    {{ form_field(form.body,rows=5,cols=50) }}
    {{form.submit}}<br>
</form>
{% endblock %}

 

1.4说明

1、index模板的渲染

2、点击new note按钮访问的url是什么?(/new)请求的方法是get还是postget

3、请求到flask之后,触发的视图函数是什么(new_note

1)new_note视图函数里,form是否做了实例化(是)

是否传入了request.form(是)

2) 表单数据是否为空(是),是否通过了表单验证(否)

——if form.validate_on_submit()

3) 视图函数处理的结果是渲染了哪个模板(new_note.html),到哪个页面?new_note.html

4) New_note页面填入表单数据后,处罚的请求方式是啥(post),页面请求啥(/new/

到哪个视图函数下处理(new_note),是否表单数据验证通过(是),视图函数的结果是渲染的哪个页面(index),数据是怎么处理的(实例化一个note数据,存到note表里)

1.5更新app.py

 

# encoding=utf-8
from flask import Flask,render_template,flash,url_for,redirect,request
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import TextAreaField,SubmitField
from wtforms.validators import DataRequired

app = Flask(__name__)

import os
app.secret_key = os.getenv('SECRET_KEY','secret string')
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL','sqlite:///' + os.path.join(app.root_path,'data.db'))
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

# 该方法跟模板上下文函数类似,返回的是一个字典,将对象以key和value
@app.shell_context_processor
def make_shell_content():
    return dict(db=db,Note=Note,Author=Author,Article=Article,Writer=Writer,Book=Book)

class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(70), unique=True)
    articles = db.relationship('Article') #定义关联函数,关联属性,一对多的一,即为标量,出发侧,参数是关联的模型类


    def __repr__(self):
        return '<Author id: %r, name: %r>' % (self.id, 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')) #定义外键,集合属性就是多

    # 指定显示内容,否则默认显示<表名 主键id>
    def __repr__(self):
        return '<Article id: %r, title: %r, body: %r, author_id: %r>' % (self.id, self.title,self.body,self.author_id)


class Writer(db.Model):
    id = db.Column(db.Integer,primary_key = True)
    name = db.Column(db.String(70),unique = True)
    # back_populats定义双向关系
    # back_populats参数的值需要设为关系另一侧的关系属性名
    books = db.relationship('Book', back_populates='writer')

    def __repr__(self):
        return '<Writer id: %r, name: %r>' %(self.id,self.name)


class Book(db.Model):
    id = db.Column(db.Integer,primary_key = True)
    title = db.Column(db.String(50), primary_key=True)
    writer_id = db.Column(db.Integer, db.ForeignKey('writer.id'))
    writer = db.relationship('Writer', back_populates='books')

    def __repr__(self):
        return '<Book id: %r, title: %r, writer_id:%r>' %(self.id,self.title,self.writer_id)
#
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')
    # songs = relationship('song',backref=backref('singer',uselist=False))

    def __repr__(self):
        return '<Singer id: %r, name: %r>' %(self.id,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 '<Song id: %r, name: %r>' %(self.id,self.name)
#
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'))
    # back_population的值为另一侧的关系属性名
    # city = db.relationship('City')
    # relationship函数的第一个参数是另一侧的模型名(类型)
    city = db.relationship('City', back_populates='citizen')
    def __repr__(self):
        return '<Citizen id: %r, name: %r, city_id: %r>' %(self.id,self.name,self.city_id)
#
class City(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(30), unique=True)
    # back_population的值为另一侧的关系属性名
    # relationship函数的第一个参数是另一侧的模型名(类型)
    citizen = db.relationship('Citizen', back_populates='city')
    def __repr__(self):
        return '<City id: %r, name: %r>' %(self.id,self.name)
#
# 101行
class Country(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(30), unique=True)
    capital = db.relationship('Capital',uselist=False)
# 109hang
    def __repr__(self):
        return '<Country id: %r, name: %r>' %(self.id,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')

    def __repr__(self):
        return '<Capital id: %r, name: %r, country_id: %r>' %(self.id,self.name,self.country_id)
# 多对多关系
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')),

                             )
# 125行代码
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 '<Student id: %r, name: %r, grade: %r>' %(self.id, self.name,self.grade)
# 135行行号
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))
    # black_populates,定义双向关系
    # back_populations参数的值需要设为关系另一侧的关系属性名
    students = db.relationship('Student',
                               secondary = association_table,
                               back_populates = 'teachers') # collection
    def __repr__(self):
        return '<Teacher id: %r,name: %r,office: %r>' %(self.id,self.name,self.office)

#定义Note模型类,映射到表note
class Note(db.Model):
    id = db.Column(db.Integer,primary_key = True)
    body = db.Column(db.Text)

    def __repr__(self):
        # %r 是用repr()方法处理对象,返回类型本身,而不进行类型转化
        return '<Note id: %r, body: %r>' % (self.id,self.body)


class NewNoteForm(FlaskForm):
    body = TextAreaField('Body',validators=[DataRequired()]) # 跳转新页面的body框
    submit = SubmitField('Save')

class EditNoteForm(FlaskForm):
    body = TextAreaField('Body',validators=[DataRequired()])
    submit = SubmitField('Update')

class DeleteNoteForm(FlaskForm):
    submit = SubmitField('Delete')

import click
@app.cli.command()
def initdb():
  db.create_all()
  click.echo('Initialized database')

@app.route('/new/',methods=['GET','POST'])
def new_note():
    print("request.form in new_note: %s" % request.form)
    form = NewNoteForm()
    print("form:" , form)
    print("form.validate_on_submit(): " ,form.validate_on_submit())
    # if request.method == 'POST' and form validate():
    if form.validate_on_submit():
        print("pass")
        try:
            print(Note.query.all())
        except:
            print("initdb...")
            initDB()
        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/<int:note_id>',methods=['GET','POST'])
def edit_note(note_id):
    print("request.form in edit_note: %s" % request.form)
    form = EditNoteForm()
    print("form.body: %s"  % form.body)
    print("form.body.data: %s"  % form.body.data)
    note = Note.query.get(note_id)
    print("note.body: %s" % note.body)
    if form.validate_on_submit(): # 判断表单提交的数据是否不为空+是post请求
        print("validated")
        note.body = form.body.data # 赋值新值
        print("note.body in validate: %s" % note.body)
        db.session.commit()
        flash("your note is edited")
        return redirect(url_for('index'))
    form.body.data = note.body #
    return render_template('edit_note.html',form=form)

@app.route('/delete/,<int:note_id>',methods=['POST'])
def delete_note(note_id):
    form = DeleteNoteForm()
    if form.validate_on_submit():
        note = Note.query.get(note_id) #获取对应记录
        db.session.delete(note) #删除记录
        db.session.commit() # 提交修改
        flash('Your note is deleted')
    else:
        abort(400)
    return redirect(url_for('index'))
@app.route('/index/')
def index():
    db.create_all()
    form = NewNoteForm
    form_delete = DeleteNoteForm()
    notes = Note.query.all()
    return render_template('index.html',notes=notes,form=form,form_delete=form_delete)


if __name__ == "__main__":
    print(app.config)
    app.run(debug=True)

 

1.5.1说明:

@app.shell_context_processor装饰器的作用,自动返回所有类对象

@app.shell_context_processor
def make_shell_content():
    return dict(db=db,Note=Note,Author=Author,Article=Article,Writer=Writer,Book=Book)

1.6操作查看

启动flask

.pipenv shell启动之后

再次执行flask shell

 

 

>>> db
<SQLAlchemy engine=sqlite:///E:\FlaskTest\data.db>
>>> Note
<class 'app.Note'>
>>> Author
<class 'app.Author'>
>>>

二、一对多(单向关系)

只能一对多,去查

 

 2.1声明表的绝对路径

 

 

db

db.create_all()

之后,成功新建了定义的以类名做表名的数据

 

 

 

2.2数据可作实例化

>>> a1
<Author id: None, name: 'xxx'>
>>>
>>> b1 = Article(title = 'yyy')
>>> b1
<Article id: None, title: 'yyy', body: None, author_id: None>
>>>
>>> db.session.add_all([a1,b1]) # 多个数据的提交
>>> db.session.commit()
>>>

 

>>> a1
<Author id: 1, name: 'xxx'>
>>> b1
<Article id: 1, title: 'yyy', body: None, author_id: None>
>>>

 

# 把b1加到a1的关系里面
>>>
>>> a1.articles
[]
>>> a1.articles.append(b1)
>>> a1.articles
[<Article id: 1, title: 'yyy', body: None, author_id: None>]
>>>

 

# commit提交之后的效果(append)
>>> a1.articles  #查看a1的articles属性
[<Article id: 1, title: 'yyy', body: None, author_id: None>]
>>> db.session.commit()
>>> a1.articles
[<Article id: 1, title: 'yyy', body: None, author_id: 1>]
>>>

 

# 再次新增数据(指定外键)
>>> b2 = Article(title = 'qwerty')
>>> b2.author_id = 1
>>> a1.articles
[<Article id: 1, title: 'yyy', body: None, author_id: 1>]
>>> db.session.add(b2)
>>> db.session.commit()
>>> a1.articles
[<Article id: 1, title: 'yyy', body: None, author_id: 1>, <Article id: 2, titl
e: 'qwerty', body: None, author_id: 1>]
>>>

 

# 查找出id=3的数据
>>> b3 = Article(title = 'sdfgh')
>>> db.session.add(b3)
>>> db.session.commit()
>>> b3
<Article id: 3, title: 'sdfgh', body: None, author_id: None>
>>>
>>> st = Article.query.get(3)
>>> st
<Article id: 3, title: 'sdfgh', body: None, author_id: None>

 

# 新增了一条数据
>>> a1.articles
[<Article id: 1, title: 'yyy', body: None, author_id: 1>, <Article id: 2, titl
e: 'qwerty', body: None, author_id: 1>]
>>> a1.articles.append(b3)
>>> a1.articles
[<Article id: 1, title: 'yyy', body: None, author_id: 1>, <Article id: 2, titl
e: 'qwerty', body: None, author_id: 1>, <Article id: 3, title: 'sdfgh', body:
None, author_id: None>]
>>>

 

通过切片取值
>>> a1.articles = a1.articles[0:2]
>>> a1.articles
[<Article id: 1, title: 'yyy', body: None, author_id: 1>, <Article id: 2, titl
e: 'qwerty', body: None, author_id: 1>]
>>>

 

#删除关联关系的这1整条数据
a1.articles.remove(b1)

 

db.sesson.rollback()
a1.articles #数据又还原回来了

 

 

三、一对多的双向关系

 

posted @ 2022-04-30 00:34  翻滚的小强  阅读(45)  评论(0)    收藏  举报