【Django入门】通过模型类查询MySQL数据库基本操作

通过【Django入门】——配置Django使用MySQL数据库我们知道了如何配置Django使用MySQL数据库;在【Django入门】——Django中通过模型类实现数据表基本操作中我们也知道了通过在框架的models.py文件定义的模型类可以进行数据表的基本操作。

本文将着重于记录如何通过模型类实现数据表的查询相关操作。

另外,本文通过各种方式查询出来的结果都是QuerySet类型的对象,针对该对象可以继续使用本文介绍的所有查询方式。关于QuerySet的进一步介绍,请参考文章【Django入门】——查询集QuerySet介绍

一、创建演示环境

1. 创建项目

首先,结合【Django入门】——从零开始创建并启动一个Django项目创建一个Django项目test3,并在其中新建一个名为booktest的应用且完成相应配置。

2. 配置数据库

接着,结合【Django入门】——配置Django使用MySQL数据库,创建一个MySQL数据库db4_test3,然后配置上述Django项目test3使用该db4_test3

3. 生成数据表

3.1 定义模型类

首先在应用booktestmodels.py文件中定义如下的两个模型类:

from django.db import models


# Create your models here.
class BookInfo(models.Model):
    """图书模型类"""
    book_title = models.CharField(max_length=20)  # 图书名称
    book_pub_date = models.DateField()  # 出版日期
    book_read = models.IntegerField(default=0)  # 阅读量,默认为0
    book_comment = models.IntegerField(default=0)  # 评论量,默认为0
    is_delete = models.BooleanField(default=False)  # 软删除标记,默认不删除


class HeroInfo(models.Model):
    """英雄任务模型类"""
    hero_name = models.CharField(max_length=20)  # 英雄名字
    hero_gender = models.BooleanField(default=False)  # 性别默认为男
    hero_desc = models.CharField(max_length=200)  # 英雄的描述信息
    hero_book = models.ForeignKey('BookInfo', models.CASCADE)  # 关系属性
    is_delete = models.BooleanField(default=False)

3.2 迁移生成表

此步骤中,首先需要生成迁移文件并执行迁移命令,而后通过终端连接MySQL数据库,可以查看数据库db4_test3数据库中的数据表及其详情如下:

mysql> use db4_test3;
Database changed
mysql> show tables;
Empty set (0.00 sec)

mysql> show tables;
+----------------------------+
| Tables_in_db4_test3        |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| booktest_bookinfo          |
| booktest_heroinfo          |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+
12 rows in set (0.00 sec)

mysql> desc booktest_bookinfo;
+---------------+-------------+------+-----+---------+----------------+
| Field         | Type        | Null | Key | Default | Extra          |
+---------------+-------------+------+-----+---------+----------------+
| id            | int(11)     | NO   | PRI | NULL    | auto_increment |
| book_title    | varchar(20) | NO   |     | NULL    |                |
| book_pub_date | date        | NO   |     | NULL    |                |
| book_read     | int(11)     | NO   |     | NULL    |                |
| book_comment  | int(11)     | NO   |     | NULL    |                |
| is_delete     | tinyint(1)  | NO   |     | NULL    |                |
+---------------+-------------+------+-----+---------+----------------+
6 rows in set (0.02 sec)

mysql> desc booktest_heroinfo;
+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| id           | int(11)      | NO   | PRI | NULL    | auto_increment |
| hero_name    | varchar(20)  | NO   |     | NULL    |                |
| hero_gender  | tinyint(1)   | NO   |     | NULL    |                |
| hero_desc    | varchar(200) | NO   |     | NULL    |                |
| is_delete    | tinyint(1)   | NO   |     | NULL    |                |
| hero_book_id | int(11)      | NO   | MUL | NULL    |                |
+--------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

3.3 插入案例数据

使用下列命令向booktest_bookinfo数据表中插入数据:

insert into booktest_bookinfo(book_title, book_pub_date, book_read, book_comment, is_delete) values
('射雕英雄传', '1980-5-1', 12, 34, 0),
('天龙八部', '1986-7-24', 36, 40, 0),
('笑傲江湖', '1995-12-24', 20, 80, 0),
('雪山飞狐', '1987-11-11', 58, 24, 0);

使用下列命令向booktest_heroinfo数据表中插入数据:

insert into booktest_heroinfo(hero_name, hero_gender, hero_book_id, hero_desc, is_delete)  values
    ('郭靖', 1, 1, '降龙十八掌', 0),
    ('黄蓉', 0, 1, '打狗棍法', 0),
    ('黄药师', 1, 1, '弹指神通', 0),
    ('欧阳锋', 1, 1, '蛤蟆功', 0),
    ('梅超风', 0, 1, '九阴白骨爪', 0),
    ('乔峰', 1, 2, '降龙十八掌', 0),
    ('段誉', 1, 2, '六脉神剑', 0),
    ('虚竹', 1, 2, '天山六阳掌', 0),
    ('王语嫣', 0, 2, '神仙姐姐', 0),
    ('令狐冲', 1, 3, '独孤九剑', 0),
    ('任盈盈', 0, 3, '弹琴', 0),
    ('岳不群', 1, 3, '华山剑法', 0),
    ('东方不败', 0, 3, '葵花宝典', 0),
    ('胡斐', 1, 4, '胡家刀法', 0),
    ('苗若兰', 0, 4, '黄衣', 0),
    ('程灵素', 0, 4, '医术', 0),
    ('袁紫衣', 0, 4, '六合拳', 0);

二、常用查询函数

通过模型类.objects属性调用如下函数,可实现对和模型类对应数据表相关查询操作:

1. get

  • 功能:返回数据表中满足条件的一条且只能有一条数据;
  • 返回值:一个模型类对象;
  • 参数:查询条件;
  • 说明
    • 如果查询到多条数据,则抛出异常MultipleObjectsReturned
    • 如果查询不到数据,则抛出异常DoesNotExist。 |
$ python manage.py shell
Python 3.6.9 (default, Jul 17 2020, 12:50:27) 
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from booktest.models import BookInfo
>>> book = BookInfo.objects.get(id=1)
>>> book
<BookInfo: BookInfo object (1)>

2. all

  • 功能:返回模型类对应数据表中的所有数据;
  • 返回值QuerySet类型。
>>> books = BookInfo.objects.all()
>>> books
<QuerySet [<BookInfo: BookInfo object (1)>, <BookInfo: BookInfo object (2)>, <BookInfo: BookInfo object (3)>, <BookInfo: BookInfo object (4)>]>
>>> type(books)
<class 'django.db.models.query.QuerySet'>

3. filter

  • 功能:返回满足筛选条件的数据;
  • 返回值QuerySet类型;
  • 参数:查询条件。

注:查询条件的格式一般为:模型类属性名__条件名=值

  • 模糊查询:

例如,查询书名中包含’传’的图书记录:

>>> BookInfo.objects.filter(book_title__contains='传')
<QuerySet [<BookInfo: BookInfo object (1)>]>
  • 模糊查询:

例如,查询以’部’结尾的图书记录:

>>> BookInfo.objects.filter(book_title__endswith='部')  
<QuerySet [<BookInfo: BookInfo object (2)>]>
  • 空查询:

例如,查询书名不为空的图书记录:

>>> BookInfo.objects.filter(book_title__isnull=False);
<QuerySet [<BookInfo: BookInfo object (1)>, <BookInfo: BookInfo object (2)>, <BookInfo: BookInfo object (3)>, <BookInfo: BookInfo object (4)>]>
  • 范围查询:

例如,查询id为1或3或5的图书记录:

>>> BookInfo.objects.filter(id__in = [1, 3, 5])
<QuerySet [<BookInfo: BookInfo object (1)>, <BookInfo: BookInfo object (3)>]>

上述范围查询语句实际上相当于:

select * from booktest_bookinfo where id in (1, 3, 5);
  • 比较查询:

例如,查询id大于3的图书记录:

>>> BookInfo.objects.filter(id__gt = 3)
<QuerySet [<BookInfo: BookInfo object (4)>]>

再例如,查询id小于等于3的图书记录:

>>> BookInfo.objects.filter(id__lte = 3)
<QuerySet [<BookInfo: BookInfo object (1)>, <BookInfo: BookInfo object (2)>, <BookInfo: BookInfo object (3)>]>
  • 日期查询:

例如,查询1980年发表的图书记录:

>>> BookInfo.objects.filter(book_pub_date__year = 1980)
<QuerySet [<BookInfo: BookInfo object (1)>]>

再例如,查询1980年1月1日以后发表的图书记录:

>>> BookInfo.objects.filter(book_pub_date__gt=date(1980, 1, 1))
<QuerySet [<BookInfo: BookInfo object (1)>, <BookInfo: BookInfo object (2)>, <BookInfo: BookInfo object (3)>, <BookInfo: BookInfo object (4)>]>

4. exclude

  • 功能:数据表中不满足条件的数据;
  • 返回值QuerySet类型。

例如,查询图书id不为3的图书记录:

>>> BookInfo.objects.exclude(id=3)
<QuerySet [<BookInfo: BookInfo object (1)>, <BookInfo: BookInfo object (2)>, <BookInfo: BookInfo object (4)>]>

5. order_by

  • 功能:对查询结果进行排序;
  • 返回值QuerySet类型。

例如,查询出图书信息表中所有的图书记录,按照id从小到大进行排序:

>>> BookInfo.objects.all().order_by('id')
<QuerySet [<BookInfo: BookInfo object (1)>, <BookInfo: BookInfo object (2)>, <BookInfo: BookInfo object (3)>, <BookInfo: BookInfo object (4)>]>

order_by参数默认以升序进行排序。

再例如,查询出图书信息表中所有的图书记录,按照id从大到小进行排序(即降序):

>>> BookInfo.objects.all().order_by('-id')
<QuerySet [<BookInfo: BookInfo object (4)>, <BookInfo: BookInfo object (3)>, <BookInfo: BookInfo object (2)>, <BookInfo: BookInfo object (1)>]>

实际上,上述查询语句相当于:

select * from booktest_bookinfo order by id DESC;

最后,再如将id大于1的图书记录按照阅读量从大到小进行排序:

>>> BookInfo.objects.filter(id__gt=1).order_by('book_read')
<QuerySet [<BookInfo: BookInfo object (3)>, <BookInfo: BookInfo object (2)>, <BookInfo: BookInfo object (4)>]>

三、查询条件的Q对象

同一个函数可能包含多个条件,当多个条件之间存在与、或、非的关系时,就要用到Django框架中的Q对象,在使用时需要从django.db.models中导入Q

  • 查询图书id大于3或图书阅读量book_read大于30的图书记录:
>>> from django.db.models import Q
>>> BookInfo.objects.filter(Q(id__gt=3) | Q(book_read__gt=30))
<QuerySet [<BookInfo: BookInfo object (2)>, <BookInfo: BookInfo object (4)>]>
  • 查询id不等于3的图书记录:
>>> BookInfo.objects.filter(~Q(id=3))
<QuerySet [<BookInfo: BookInfo object (1)>, <BookInfo: BookInfo object (2)>, <BookInfo: BookInfo object (4)>]>

四、类属性比较的F对象

如果希望查询数据表中的记录,要求每一条记录的字段之间满足一定的要求,则此时就需要使用django.db.models中的F

例如,查询图书信息表中阅读量大于评论量的图书记录:

>>> from django.db.models import F
>>> BookInfo.objects.filter(book_read__gt=F('book_comment'))
<QuerySet [<BookInfo: BookInfo object (4)>]>

五、聚合函数查询

MySQL数据库入门(3)——数据库查询操作中我们知道,通过使用聚合函数,MySQL支持通用统计函数进行查询。同样,在使用模型类查询数据表时也支持类似求和sum、计数count、均值avg、最大值max、最小值min等聚合查询。

在Django中,为了对查询的结果集QuerySet使用聚合操作,需要调用aggregate函数,该函数的返回值是一个字典。

在使用对应的聚合查询操作之前,需要通过下列语句导入对应的类:

from django.db.models import Sum, Count, Max, Min, Avg
  • 查询数据表中图书记录条数:
>>> from booktest.models import BookInfo
>>> from django.db.models import Count
>>> BookInfo.objects.all().aggregate(Count('id'))
{'id__count': 4}
  • 查询数据表中所有图书记录的阅读量综总和:

>>> from django.db.models import Sum
>>> BookInfo.objects.all().aggregate(Sum('book_read'))
{'book_read__sum': 126}

由上述查询我们还知道,函数aggregate的返回值是一个字典,且字典的键的格式为类属性名称__查询类名称

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值