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

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

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

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

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

创建好项目后,我们开始编写配置文件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框架的基础配置已经写好了,接下来我们将正式学习模型关系(一对多关系)。

一对多关系

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

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

这里我们在文章表中增加一个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数据表,如下图所示:

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

可以发现在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添加几条数据,如下图所示:

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

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

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

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

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

好了,成功添加文章后,那么我们如何在网页中展示文章标题、文章内容以及作者名呢?在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,如下图所示:

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

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

通过作者找出其文章

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

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

@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,如下图所示:

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

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

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

– END –


原文始发于微信公众号(白巧克力LIN):Flask框架——模型关系(1对多)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/36236.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!