美文网首页Web开发——Flask框架
Flask框架——模型关系(1对多)

Flask框架——模型关系(1对多)

作者: 白巧克力LIN | 来源:发表于2022-07-18 00:27 被阅读0次

    上篇文章学习了Flask框架——数据库操作命令(查询、修改、删除、添加),这篇文章我们学习Flask框架——模型关系(一对多关系)。

    在一个完整的系统中,数据库、数据表是必不可少的,数据表与表之间有着一定的联系,互相影响着,而Flask框架与数据库有关的是模型,那么如何使模型之间产生联系呢。模型之间有两种关系:一对多、多对多。

    在讲解模型之间关系前,首先我们创建一个Flask项目,其目录如下所示:



    创建好项目后,我们开始编写配置文件settings.py的代码,如下所示:

    class Configs:
        ENV='development'
        DEBUG=True
        # 设置连接数据库路径
        SQLALCHEMY_DATABASE_URI='mysql+pymysql://root:123456@127.0.0.1:3306/test'
        # 每次请求结束后自动提交数据库中的改动
        SQLALCHEMY_COMMIT_ON_TEARDOWN=True
        # 禁用SQLAlchemy对追踪对象的修改并且发送信号
        SQLALCHEMY_TRACK_MODIFICATIONS = False
    

    编写好配置文件后,我们将配置文件导入app.py文件中,代码如所示:

    from flask import Flask
    from settings import Config
    
    app = Flask(__name__)
    app.config.from_object(Config)  # 加载配置
    
    if __name__ == '__main__':
        app.run()
    

    好了,Flask框架的基础配置已经写好了,接下来我们将正式学习模型关系(一对多关系)。

    一对多关系

    我们拿用户与文章为例子,一个用户可以发布多篇文章,所以它们是一对多关系,我们假设数据库中用户表与文章表如下图所示:



    这里我们在文章表中增加一个user_id字段来标志是哪个用户发表的文章,当我们想要找出张三所发表的所有文章时,只需要在文章表中搜索user_id为001的数据并输出即可。

    在数据库中,数据表是这样设计,那么如何使模型之间产生联系呢,如何编写模型之间产生联系的代码呢?

    ForeignKey外键

    要想数据表产生联系,主外键是必不可少的,在Flask框架中,可以通过ForeignKey方法在模型类中设置外键,这里我们在文章Article模型类中设置外键,代码如下所示:

    from flask_sqlalchemy import SQLAlchemy
    db=SQLAlchemy(app=app,use_native_unicode="utf8")       # 创建映射对象db
    
    class Article(db.Model):
        __tablename__ = 'article'       #数据表名
        id=db.Column(db.Integer,primary_key=True,autoincrement=True)    #文章id为主键,自增
        title=db.Column(db.String(50),nullable=False)       #文章标题title
        content=db.Column(db.Text,nullable=False)           #文章内容content
        click_num=db.Column(db.Integer,default=0)           #文章点击数click_num,默认值为0
        user_id=db.Column(db.Integer,db.ForeignKey('user.id'),nullable=False)   #设置user_id字段为user数据表的外键
    

    我们使用db.ForeignKey()方法将user_id字段设置为user数据表的外键,其方法传入的参数为产生联系的模型类数据表中的主键,注意:在一对多关系中,外键是设置在多的那方。

    这样article数据表与user数据表产生了联系,那么是不是这样就可以了呢?答案是:不是。

    relationship()方法

    有了外键后,还需要使用relationship()让模型类之间产生联系,这里我们在User用户模型类中使用relationship()方法,代码如下所示:

    class User(db.Model):
        __tablename__ = 'user'       #数据表名
        id=db.Column(db.Integer,primary_key=True,autoincrement=True)    #文章id为主键,自增
        username=db.Column(db.String(15),nullable=False)               #用户名username
        password=db.Column(db.String(64),nullable=False)               #用户密码password
        phone=db.Column(db.String(11),unique=True)                     #用户手机号phone
        isdelete=db.Column(db.Boolean,default=False)                   #字段isdelete,用来判断用户是否被删
        articles=db.relationship('Article',backref='user',lazy='dynamic')   #设置articles,其作用为使User模型类与其他模型类产生联系
    

    我们使用了db.relationship()方法将该模型类与其他模型类产生联系。其中:第一个参数为你要产生联系的模型类,这里我们要产生联系的模型类为Article ;第二个参数backref为反向引用,其参数值可以是任意的,我们通过该参数值调用Article里面的属性字段;第三个参数lazy为数据加载,其参数值可以为:

    • select:默认值,SQLAlchemy 会使用一个标准的 select 语句必要时一次加载数据;
    • joined:告诉 SQLAlchemy 使用 JOIN 语句作为父级在同一查询中来加载关系;
    • subquery:类似joined,但是SQLAlchemy会使用子查询;
    • dynamic:在有多条数据的时候是特别有用的,不是直接加载这些数据,SQLAlchemy会返回一个查询对象,在加载数据前我们可以过滤(提取)它们。

    一般情况下,lazy参数值我们会选择默认值,也就是说我们不需要写lazy参数。

    注意:

    • articles字段不会在数据表中体现出来,articles字段主要作用于模板与视图函数;
    • db.relationship()只能定义在两个要互相关联的模型类中任意一个模型类。

    查看数据表

    好了,模型类的代码已经写好了,接下来我们通过编写代码创建数据表,其代码如下所示:

    if __name__ == '__main__':
        db.create_all()         #创建数据表
        app.run()
    

    在终端执行app.py文件后,就成功创建好数据表了。下面我们在终端看看user、article数据表,如下图所示:




    可以发现在user数据表中,没有articles字段,该字段是使用了db.relationship()方法,而不是使用db.Column()方法,所以不会在数据表中展示该字段,该字段作用是使模型类与模型类之间产生联系。

    是不是模型关系——一对一关系就讲完了呢?NO,NO,NO,为了大家更直观地感受模型关系——一对一关系,我们通过编写代码使用模板来演示。

    实例演示

    添加文章数据

    首先我们在app.py文件中创建一个视图函数,用来添加文章数据,代码如下所示:

    @app.route('/publish',methods=['GET','POST'])
    def article():
        if request.method=='POST':          #当请求为POST请求时
            title=request.form.get('title')  #获取请求中的title
            content=request.form.get('content') #获取请求中的content
            uid=request.form.get('uid')     #获取请求中的uid
            
            article=Article()   #创建文章模型类实例对象    
            #将获取到的title、content、uid数据传递到实例对象article的title、content、user_id中
            article.title=title
            article.content=content
            article.user_id=uid
            #将获取到的数据保存在article数据表中
            db.session.add(article)     #添加数据
            db.session.commit()         #提交事务
            return '添加成功'
        else:
            #当不是POST请求时
            users=User.query.filter(User.isdelete==False).all() #找出所有user数据表中isdelete为False的数据
            return render_template('add_article.html',users=users)  #通过render_template()方法渲染add_article.html并传递users到网页中
    

    编写好视图函数后,接下来在templates文件夹中创建一个名为add_article的html文件,其代码如下所示:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>添加文章</title>
    </head>
    <body>
    <form action="{{ url_for('article') }}" method="post">
        <p><input type="text" name="title" placeholder="文章标题"></p>
        <p>
            <textarea cols="50" rows="10" placeholder="输入文章内容" name="content"></textarea>
        </p>
        <p>
            用户:
            <select name="uid">
                <option value="0">请选择用户</option>
                {% for user in users  %}
                    <option value="{{ user.id }}">{{ user.username }}</option>
                {% endfor %}
            </select>
        </p>
        <p><input type="submit" value="添加文章"></p>
    </form>
    </body>
    </html>
    

    在运行我们Flask项目前,我们先在user添加几条数据,如下图所示:


    添加数据后,我们在终端执行app.py,并在浏览器中打开http://127.0.0.1:5000/publish,如下图所示:

    当我们点击添加文章时,就会显示添加成功,添加成功后,我们再添加几条数据,如下图所示:

    好了,成功添加文章后,那么我们如何在网页中展示文章标题、文章内容以及作者名呢?在article数据表中是没有作者名的,只有user_id,那么如何获取到作者名呢?

    通过文章获取作者名

    通过文章获取作者名,首先我们在app.py文件中编写视图函数,代码如下所示:

    @app.route('/all_article')
    def all_article():
        articles=Article.query.all()        #查询所有文章数据
        return render_template('all_article.html',articles=articles)    #通过render_template()方法渲染all_article.html并传递articles到网页中
    

    编写好视图函数后,接下来在templates文件夹中创建一个名为all_article的html文件,其代码如下所示:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {# 获取文章数据列表 #}
    {% for article in articles %}
        <div id="container">
            <p>
                <h2>{{ article.title }}</h2>
                <div>作者:{{ article.user.username }}</div>
            </p>
            <p>{{ article.content }}</p>
        </div>
    {% endfor %}
    </body>
    </html>
    

    首先我们通过视图函数传递的articles获取到文章列表,再通过articles遍历获取文章内容与标题,注意第十二行代码,刚才我们在想如何获取作者名,在编写用户模型类时添加了articles字段,其代码如下所示:

    articles=db.relationship('Article',backref='user',lazy='dynamic')
    

    这个反向引用backref参数值user就很用有了,我们通过article.user获取user模型类对象,这样就有了user的属性了,再通过.username获取user中的username属性,这个属性也就是作者名了,在终端执行app.py,并在浏览器中打开http://127.0.0.1:5000/all_article,如下图所示:

    这样我们成功获取到了文章标题、内容、作者名。

    通过作者找出其文章

    问题来了,当我们通过作者来找出其所有文章数据,该如何编写代码呢?

    首先我们创建一个视图函数,代码如下所示:

    @app.route('/author')
    def author():
        id=request.args.get('id')       #获取请求的id号
        user=User.query.get(id)         #找出请求id的用户数据
        return render_template('author.html',user=user)     #通过render_template()方法渲染author.html并传递user到网页中
    

    编写好视图函数后,接下来在templates文件夹中创建一个名为author的html文件,其代码如下所示:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    {# 获取文章数据列表 #}
    {% for article in user.articles %}
        <div id="container">
            <p>
                <h2>{{ article.title }}</h2>
                <div>作者:{{ user.username }}</div>
            </p>
            <p>{{ article.content }}</p>
        </div>
    {% endfor %}
    </body>
    </html>
    

    该模板author.html文件与通过文章获取作者名的all_article.html文件类似,只是第八行和第十二行代码发生了改变。

    第八行代码,将视图函数传递的user中.articles获取文章数据对象,获取到文章数据对象后就有了该对象的属性,这个articles就是我们User模型类中的articles字段,user.articles返回的是文章数据列表,第十二行代码直接通过user.username获取到用户名。

    在终端执行app.py,并在浏览器中打开http://127.0.0.1:5000/author?id=1,如下图所示:


    这里我们获取了用户id为1,也就是用户名为zhangsan的文章数据。

    好了,Flask框架——模型关系(一对多关系)的相关知识就讲到这里了,下篇文章继续Flask框架——模型关系(多对多关系),感谢观看!!!
    公众号:白巧克力LIN

    相关文章

      网友评论

        本文标题:Flask框架——模型关系(1对多)

        本文链接:https://www.haomeiwen.com/subject/bzrrirtx.html