zoukankan      html  css  js  c++  java
  • 06-综合案例(一对多)

    综合案例-图书管理

      1、WTF表单

      2、数据库操作

      3、一对多关系演练

    定义模型

      模型表示程序使用的数据实体,在Flask-SQLAlchemy中,模型一般是Python类,继承自db.Model,db是SQLAlchemy类的实例,代表程序使用的数据库。

      类中的属性对应数据库表中的列。id为主键,是由Flask-SQLAlchemy管理。db.Column类构造函数的第一个参数是数据库列和模型属性类型。

    如果想修改数据库编码:

    alter database 数据库名 CHARACTER SET utf8;

    定义两个模型类:作者和书名:

    from flask import Flask,render_template,redirect,url_for
    from flask_sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    
    #设置连接数据库 root是用户名 冒号后面是密码
    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:mysql@127.0.0.1:3306/flasksql"
    
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
    
    #实例化SQLAlchemy对象,对谁操作
    db = SQLAlchemy(app)
    #定义模型类-作者
    class Author(db.Model):
        #设置表名:author
        __tablename__ = "authors"
        #设置 id列
        id = db.Column(db.Integer,primary_key=True)
        name = db.Column(db.String(32),unique=True)
        #一对多,所以在一的地方声明关系,与哪张表,backref为类Author申明新属性的方法
        au_book = db.relationship("Book",backref="author")
        def __repr__(self):
            return "Author:%s"%self.name
    
    #定义模型类-书名 多对一
    class Book(db.Model):
        __tablename__ = "books"
        id = db.Column(db.Integer,primary_key=True)
        name = db.Column(db.String(32))
        #关联那个外键表,多对一 首先外键对应的是 模型类小写点属性
        au_book = db.Column(db.Integer,db.ForeignKey("author.id"))
        def __repr__(self):
            return "Book:%s,%s"%(self.name,self.id)

     

    创建表

    #创建表
    if __name__ == '__main__':
        #建表之前需要将数据库中的表清除完
        db.drop_all()
        db.create_all()
        app.run(debug=True)
        
        

    查看表成功创建。

    添加数据测试一下:

    #生成数据
    au1 = Author(name='老王')
    au2 = Author(name='老尹')
    au3 = Author(name='老刘')
    # 把数据提交给用户会话
    db.session.add_all([au1, au2, au3])
    # 提交会话
    db.session.commit()
    bk1 = Book(name='老王回忆录', au_book=au1.id)
    bk2 = Book(name='我读书少,你别骗我', au_book=au1.id)
    bk3 = Book(name='如何才能让自己更骚', au_book=au2.id)
    bk4 = Book(name='怎样征服美丽少女', au_book=au3.id)
    bk5 = Book(name='如何征服英俊少男', au_book=au3.id)
    # 把数据提交给用户会话
    db.session.add_all([bk1, bk2, bk3, bk4, bk5])
    # 提交会话
    db.session.commit()

    数据显示&表单添加

    定义路由函数,并将Author和Book的所有结果传到模板

    @app.route('/',methods=['GET','POST'])
    def index():
        author = Author.query.all()
        book = Book.query.all()
        return render_template('index.html',author=author,book=book)

    模板:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <ul>
        {% for x in author %}
        <li>{{ x }}</li>
        {% endfor %}
    </ul>
    <hr>
    <ul>
        {% for x in book %}
        <li>{{ x }}</li>
        {% endfor %}
    </ul>
    </body>
    </html>

    表单添加  

      定义表单类

    from flask_wtf import FlaskForm
    from wtforms.validators import DataRequired
    from wtforms import StringField,SubmitField
    #创建表单类,用来添加信息
    class Append(FlaskForm):
        au_info = StringField(validators=[DataRequired()])
        bk_info = StringField(validators=[DataRequired()])
        submit = SubmitField('添加')

    传入模板中:

    @app.route('/',methods=['GET','POST'])
    def index():
        author = Author.query.all()
        book = Book.query.all()
        form = Append()
        return render_template('index.html',author=author,book=book,form=form)

    模板中的代码;

    <form method="post">
        {{ form.csrf_token }}
        <p>作者:{{ form.au_info }}</p>
        <p>书名:{{ form.bk_info }}</p>
        <p>{{ form.submit }}</p>
    </form>

    表单验证

    from flask import Flask,render_template,redirect,url_for,flash,request
    from flask_sqlalchemy import SQLAlchemy
    from flask_wtf import FlaskForm
    from wtforms.validators import DataRequired
    from wtforms import StringField,SubmitField
    
    app = Flask(__name__)
    #设置密钥
    app.config["SECRET_KEY"] = "SECRET_KEY"
    
    #设置连接数据库
    app.config["SQLALCHEMY_DATABASE_URI"] = "mysql://root:@127.0.0.1:3306/flasksql"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
    
    #查询时会显示原始SQL
    app.config["SQLALCHEMY_ECHO"] = True
    
    #实例化SQLAlchemy对象,对谁操作
    db = SQLAlchemy(app)
    #定义模型类-作者
    class Author(db.Model):
        #设置表名:author
        __tablename__ = "authors"
        #设置 id列
        id = db.Column(db.Integer,primary_key=True)
        name = db.Column(db.String(32),unique=True)
        #一对多,所以在一的地方声明关系,与哪张表,backref为类Author申明新属性的方法
        us = db.relationship("Book",backref="author")
        def __repr__(self):
            return "Author:%s"%self.name
    
    #定义模型类-书名 多对一
    class Book(db.Model):
        __tablename__ = "books"
        id = db.Column(db.Integer,primary_key=True)
        name = db.Column(db.String(32))
        #关联那个外键表,多对一 首先外键对应的是 创建的表名点属性
        au_book = db.Column(db.Integer,db.ForeignKey("authors.id"))
        def __repr__(self):
            return "Book:%s,%s"%(self.name,self.id)
    #创建表单类,用来添加信息
    class Append(FlaskForm):
        au_info = StringField(validators=[DataRequired()])
        bk_info = StringField(validators=[DataRequired()])
        #这里添加u才使得这个数据完整
        submit = SubmitField(u'添加')
    # @app.route('/',methods=['GET','POST'])
    # def index():
    #     author = Author.query.all()
    #     book = Book.query.all()
    #     return render_template('index.html',author=author,book=book)
    #
    @app.route('/', methods=['get', 'post'])
    def index():
        append_form = Append()
    
        if request.method == 'POST':
            if append_form.validate_on_submit():
                #先确定值
                author_name = append_form.au_info.data
                book_name = append_form.bk_info.data
                # 判断数据是否存在
                author = Author.query.filter_by(name=author_name).first()
                if not author:
                    try:
                        # 先添加作者
                        author = Author(name=author_name)
                        db.session.add(author)
                        db.session.commit()
                        # 再添加书籍
                        book = Book(name=book_name, au_book=author.id)
                        db.session.add(book)
                        db.session.commit()
                    except Exception as e:
                        db.session.rollback()
                        print(e)
                        flash("数据添加错误")
                else:
                    #查询和这个作者相关的书名
                    book_names = [book.name for book in author.us]
                    if book_name in book_names:
                        flash('该作者已存在相同的书名')
                    else:
                        try:
                            book = Book(name=book_name, author_id=author.id)
                            db.session.add(book)
                            db.session.commit()
                        except Exception as e:
                            db.session.rollback()
                            print(e)
                            flash('数据添加错误')
            else:
                flash('数据输入有问题')
    
        authors = Author.query.all()
        books = Book.query.all()
        return render_template('test2.html', authors=authors, books=books, append_form=append_form)
    
    
    
    
    
    
    #生成数据
    # au1 = Author(name='老大')
    # au2 = Author(name='老二')
    # au3 = Author(name='老三')
    # # 把数据提交给用户会话
    # db.session.add_all([au1, au2, au3])
    # # 提交会话
    # db.session.commit()
    # bk1 = Book(name='老王回忆录', au_book=au1.id)
    # bk2 = Book(name='我读书少,你别骗我', au_book=au1.id)
    # bk3 = Book(name='如何才能让自己更骚', au_book=au2.id)
    # bk4 = Book(name='怎样征服美丽少女', au_book=au3.id)
    # bk5 = Book(name='如何征服英俊少男', au_book=au3.id)
    # # 把数据提交给用户会话
    # db.session.add_all([bk1, bk2, bk3, bk4, bk5])
    # # 提交会话
    # db.session.commit()
    #创建表
    if __name__ == '__main__':
        #建表之前需要将数据库中的表清除完
        # db.drop_all()
        # db.create_all()
        app.run(debug=True,port=8080)
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {# 重新编写html文件展示列表书籍 #}
    <h2>书籍列表</h2>
    <ul>
    {% for author in authors %}
        <li>
            {{ author.name }}
            <ul>
                {% for book in author.us %}
                    <li>{{ book.name }}
                {% else %}
                        <li>无书籍</li>
                {% endfor %}
            </ul>
    
        </li>
    {% endfor %}
    </ul>
    <form method="post">
        {{ append_form.csrf_token }}
        <p>作者:{{ append_form.au_info }}</p>
        <p>书名:{{ append_form.bk_info }}</p>
        <p>{{ append_form.submit }}</p>
    </form>
    {# 在form标签下添加 flash 消息的显示 #}
    {% for message in get_flashed_messages() %}
    {{ message }}
    {% endfor %}
    </body>
    </html>

     在form标签下添加flash消息显示

    {% for message in get_flashed_messages() %}
    {{ message }}
    {% endfor %}

    删除数据

    定义删除author和book的路由

    # 删除作者
    @app.route('/delete_author/<int:author_id>')
    def delete_author(author_id):
        author = Author.query.get(author_id)
        if not author:
            flash('数据不存在')
        else:
            try:
            #要先删除这个作者的书籍,再删除作者 Book.query.filter_by(author_id
    =author_id).delete() #删除作者
           db.session.delete(author) db.session.commit()
    except Exception as e: db.session.rollback() print(e) flash('操作数据库失败') return redirect(url_for('index')) # 删除书籍 @app.route('/delete_book/<int:book_id>') def delete_book(book_id): book = Book.query.get(book_id) if not book: flash('数据不存在') else: try: db.session.delete(book) db.session.commit() except Exception as e: db.session.rollback() print(e) flash('操作数据库失败') return redirect(url_for('index'))

    在模板中添加删除的a标签链接:

    <h2>书籍列表</h2>
    <ul>
    {% for author in authors %}
        <li>
            {{ author.name }} <a href="/delete_author/{{ author.id }}">删除</a>
            <ul>
                {% for book in author.books %}
                    <li>{{ book.name }} <a href="/delete_book/{{ book.id }}">删除</a></li>
                {% else %}
                        <li>无书籍</li>
                {% endfor %}
            </ul>
    
        </li>
    {% endfor %}
    </ul>
  • 相关阅读:
    【BZOJ】1049: [HAOI2006]数字序列(lis+特殊的技巧)
    【BZOJ】1089: [SCOI2003]严格n元树(递推+高精度/fft)
    【BZOJ】1070: [SCOI2007]修车(费用流+特殊的技巧)
    【BZOJ】1014: [JSOI2008]火星人prefix(splay+hash+二分+lcp)
    【BZOJ】1090: [SCOI2003]字符串折叠(dp)
    【BZOJ】1189: [HNOI2007]紧急疏散evacuate(二分+bfs+网络流)
    【BZOJ】3709: [PA2014]Bohater(贪心)
    【BZOJ】2929: [Poi1999]洞穴攀行(最大流)
    【BZOJ】2435: [Noi2011]道路修建(树形dp)
    【BZOJ】1458: 士兵占领(上下界网络流)
  • 原文地址:https://www.cnblogs.com/lishuntao/p/11697249.html
Copyright © 2011-2022 走看看