Django学习Day10——模型的使用(二)

Django中模型的使用

上一篇博客介绍了Django中模型的基础知识,包括ORM,Django中数据库的配置,数据字段的使用方法和数据表之间的关联关系。这一篇博客介绍Django中数据库的增、删、改、查的操作。

准备工作

首先,我们进行一些准备工作,回顾一下我们之前创建的数据表。其中,需要修改的地方是:将原数据表中的主键id字段去掉。去掉这一主键字段之后,数据库会默认生成自增的主键字段,我们不必自行传入,方便之后的操作。

数据表User:

 

数据表Userprofile(和User表是一对一的关系):

数据表Diary(和User表是一对多的关系):

数据表Group(和User表是多对多的关系;通过第三张表进行多对多的关联):

增加数据

Django中通过ORM的方式,向数据表中添加数据有四种实现方式,其中(1)(2)较为常用和方便。

(1)User.objects.create(xx=xx,xx=xx)

我们在python交互模式下,直接编写python代码来实现数据库的相关操作。在Django开发过程中,我们有时需要快速执行一些python代码,这时我们就需要用到强大的shell来编写python,但是当我们用python命令启动交互解释器时,在执行import等一些命令时,经常会报一些导入相关的错误,这是因为我们打开交互解释器之后还没有告诉Django使用哪个设置文件。解决方法:用python manage.py shell 来启动命令解释器而不要使用python,因为python manage.py shell里面已经包含了Django使用哪个settings.py文件,这样就可以直接使用python命令了。

上面已经成功添加了一条用户数据,其中user1就是User类的一个对象。我们可以在数据库中进行查看:

上一篇博客中我们有提到,我们Django中对数据字段的定义可能和数据库中查询出来显示的不是很一致,但是不影响之后的ORM操作。从这个示例即可看出,我们增加数据的时候,没有传入email的值,但是我们当时在User类中有为这些字段设置默认值,所以在数据表中会使用默认值。虽然,desc查看得到的表,显示这些这段没有默认值。

(2)user = User(xx=xx, xx=xx), user.save()

数据库中进行查看:

(3)user = User.objects.get_or_create(xx=xx, xx=xx)

在数据库中查看:

get_or_create表示:如果数据库中有这条数据就取出;如果没有这条数据就创建。

(4)user = User(), user.xx = x, user,save()

在数据库中查看:

在数据表Userprofile中增加数据:

在数据库中查看:

在数据表Diary中增加数据:

在数据库中进行查看:

因为用户和日记之间是一对多的关系,所以一个用户可以有多篇日记。

在数据表Group中增加数据:

数据表User和数据表Group之间是多对多的关系,在生成Group表时,实际上在数据库中生成了两张表app_group和app_group_user。

在app_group表中,只有三个字段:

在app_group_user表中,通过记录user_id和group_id的对应关系来保存用户和组别之间的多对多关系,如下所示:

所以在向Group表中添加数据的时候,先添加组别,之后向对应的组别中添加属于这个组别的用户,所以是分为两步:

(1)先创建不同的组别(app_group表)

在数据库中查看:

(2)向对应的小组中添加用户

在数据库中查看如下:

Django Model中get和filter的区别:

参见博客Django ORM中get和filter的区别


删除数据

在Django ORM模式中删除数据的方式是:首先获取到要删除的实例,然后执行delete()方法。

即:user = User.objects.filter(id=xx), user.delete()

这里,我们以删除用户表中的小王为例:

首先查看用户表:

删除过程如下:

查看用户表User:

查看数据表Userprofile:                                                                    查看数据表Diary:

可以看到,我们之前设置的外键中on_delete = models.SET_NULL,当用户表中删某个用户之后,在Userprofile和Diary表中,对应的user_id变为NULL。

 

修改数据

在Django ORM模式中修改数据的方式是:首先获取到要修改的实例,然后执行update()方法或者通过save()方法进行修改。

即:user = User.objects.filter(id=xx)   

       (1) user.update(xx=xx, xx=xx)     (注意当配合update使用的时候,只能使用filter,不能使用get)

       (2) user.xx = xx, user.save()

比如,我们想要修改User表中,用户名为小明的电话和邮箱:

首先查看User表如下:

修改电话phone过程如下:

查看数据表User:

修改邮箱email过程如下:

查看数据表User:

查询数据

在Django ORM中,有两种查询模式:

方法 举例 应用场景
原生sql的查询方法 User.objects.raw('select * from user') 查询条件特别复杂,或者对于查询的性能要求极高
基于ORM方法查询 User.objects.filter(id=xx) 常规的查询应用场景

使用原生sql语句查询的示例如下:

其中,原生sql语句查询中,表名需要写数据库中实际应用的表名。

我们一般的应用场景下,使用基于ORM的查询方式即可。用到的方法主要是get和filter方法,两者之间的区别我们在博客Django ORM中get和filter的区别中进行了介绍,一般来讲我们在实际应用中主要是使用filter方法,下面进行数据查询的详细介绍。

基于ORM的常用查询方法

方法名 描述
User.objects.all() 返回user表中的所有数据
User.objects.get(**filter) 返回满足所有过滤条件的数据,如果没有数据返回,会报异常
User.objects.filter(**filter) 返回满足所有过滤条件的数据,如果没有数据则返回值为空集,不报异常
User.objects.all()/filter().exists() 返回是否有对象,True   False
User.objects.all()/filter().count() 返回获取到对象的数量
User.objects.all()/filter().exclude(**filter) 返回的数据中排除满足**filter的数据
User.objects.all().values('age') 返回的数据中,以字典的形式只显示age字段
User.objects.all().values_list('age') 返回的数据中,以列表的形式只显示age字段
User.objects.filter().distinct('age') 返回的对象中通过某个列去重,但是当数据库后端使用mysql时,不适用。
User.objects.filter().order_by('age') 返回的对象中通过某个列进行排序
dir(User.objects) 显示所有可用的方法

上边的链式操作方法并不一定要依赖一级方法,可以灵活搭配使用。比如:User.objects.filter(**filter).exclude(**filter).count()等等。

以User表为例,进行查询:

示例如下:

添加一条数据,[小王,28],然后查看distinct()的使用方法,当数据库使用MySQL的时候,distinct需要配合values字段进行使用,如下所示:

排序方法order_by的使用如下:

深入查询

属性名 描述 举例
__exact sql中like 'dewei'的精准搜索情况 name__exact = 'dewei'
__iexact 精准搜索且忽略大小写 name__iexact = 'Dewei'
__contains 模糊查找,类似于sql中的like '%dewei%' name__contains = 'dewei'
__icontains 模糊查找,忽略大小写 name__icontains = 'Dewei'
__gt 大于 age__gt = 18
__gte 大于等于 age__gte = 18
__lt 小于 age__lt = 18
__lte 小于等于 age__lte = 18
__isnull 是否是空 email__isnull = True
__startswith 以什么开头 like 'dewei%' name__startswith = 'dewei'
__istartswith 以什么开头,忽略大小写 name__istartswith = 'Dewei'
__endswith 以什么结尾,like '%dewei' name__endswith = 'dewei'
__iendswith 以什么结尾,忽略大小写 name__iendswith = 'Dewei'
__in 查询是否存在列表中的数据 name__in = ['小明', '小王']

示例如下:

因为我们使用的数据库是MySQL,在MySQL中,字段值默认是不区分大小写的,即   select * from app_user where name='DeWEI'  和   select * from app_user where name='dewei'   均可以查询到用户名为dewei的记录;所以当使用MySQL数据后端时,在Django ORM中__exact和__iexact实质上是一样的。

“或”查询

聚合查询

方法名 描述 举例
Avg 平均值 User.objects.all().aggregate(Avg('age'))
Sum 取和 User.objects.all().aggregate(Sum('age'))
Max 最大值 User.objects.all().aggregate(Max('age'))
Min 最小值 User.objects.all().aggregate(Min('age'))
Count 统计数量 User.objects.all().aggregate(Count('age'))

示例如下:

Count统计的是非NULL值的数量,如下所示:

多表查询之反向查询

当表A和表B之间存在关联关系(一对一,一对多,多对多)时,通过表A模型 借助表B关联的条件 在表A中进行查找,我们称之为反向查询。

例如:我们想要查询日记内容为 “我是小张,今天天气不错!”的用户,就可以通过反向查询:即在User表中,借助Diary表的关联条件进行查询。

示例如下:

其中,diary是我们在创建Diary模型的时候,在related_name属性部分进行自定义的。

多表查询之查询关联信息

通过主对象选择需要查找的表对应的 related_name, 通过 values 查询具体信息,如下:
user = User.objects.get ( pk =1)
user.diary.values (‘content’)  -> 返回 id 1 用户的 diary content 信息
user.diary.count () -> 返回 id 1 用户的 diary 关联数量
user.diary 其实就是 Diary 模型(相当于Diary.objects),我们可以通过它再去调用更多方法,比如 get filter 再去扩展查询

比如我们想要查询小明的日记内容和小明所在的组别,示例如下:

参考资料

1、https://my.oschina.net/lonelycode/blog/741457

2、https://www.cnblogs.com/cpl9412290130/p/11777633.html

猜你喜欢

转载自blog.csdn.net/ProQianXiao/article/details/113727870