Django 6 模型与数据库 (2) 各种查询操作以及多表查询

6 篇文章 0 订阅
6 篇文章 0 订阅

Django通过模型迁移除数据库的数据表,又提供了操作数据模型的API来实现对目标数据库的读写操作。数据库的读写操作主要对数据进行增、删、 改、查。

Django带有shell模式(启动命令行和执行脚本),该模式主要为方便开发人员开发和调试程序。

在manage.py所在目录下执行以下命令即可进入shell模式:

 python manage.py shell 

导入相应的应用模型文件,就可以对模型数据进行操作 (这里以应用index为参考)。

from index.models import * 

这里以Product模型为例子,显示对其进行数据操作的步骤:

  1. 从 models.py 中导入模型 Product。
  2. 对模型 Product 声明并实例化,生成对象 p。
  3. 对象 p 的属性进行逐一赋值,对象 p 的属性来自于模型 Product 所定义的字段。完成赋值后需要对 p 进行保存才能作用在目标数据库。

现在对一下俩个表进行shell操作:

下面是三种插入操作:

# 第一种
>>> p = Product() 
>>> p . name = '荣耀 V9' 
>>> p .weight = ' lllg' 
>>> p . size = ' 120*75女 7mm ' 
>>> p . type_id = 1 
>>> p . save () 

# 第二种
#通过 Django 的 ORM 框架提供的 API 实现,使用 create 方法实现数据插入 
>>> Product.objects.create(name='荣耀 V9',weight='lllg', size='120*75*7mm',type_id=l) 

# 第三种
>>> p = Product(name='荣耀 V9',weight='lllg',size='120*75mm' ,type_id=l) 
>>> p.save() 

更新操作:

更新的实现步骤与数据插入的方法大致相同,唯一的区别是在模型实例化之后,要更新数据,需要先进行一次数据查询,将查询结果以对象的形式赋给 p,最后对 p 的属性重新赋值就能实现数据的更新。

>>> p = Product.objects.get(id=9) 
>>> p.name = '华为荣耀 V9' 
>>> p.save() 

还可以使用update方法实现单条或多条数据的更新。

#通过 Django 的 ORM 框架提供的 API 实现 
#更新单条数据,查询条件 get 适用于查询单条数据 
Product.objects.get(id=9).update(name='华为荣耀 V9') 
#更新多条数据,查询条件 filter 以列表格式返回,查询结果可能是一条或多条数据 
Product.objects.filter(name='荣耀 V9').update(name='华为荣耀 V9') 
#全表数据更新,不使用查询条件, 默认对全表的数据进行更新 
Product.objects.update(name='华为荣耀 V9') 

删除操作:

如果要对数据进行删除处理,有三种方式: 删除表中全部数据、删除一条数据和删除多条数据。

#删除表中全部数据 
Product.objects.all().delete() 
#删除一条 id 为 1 的数据 
Product.objects.get(id=l).delete() 
#删除多条数据 
Product.objects.filter(name= '华为荣耀 V9').delete () 

从上面的操作可以看出都用到了查询操作get和filter, 查询条件get和filter的区别

  • 查询条件 get: 查询字段必须是主键或者唯一约束的字段,并且查询的数据必 须存在,如果查询的字段有重复值或者查询的数据不存在,程序都会抛出异 常信息。
  • 查询条件 filter: 查询字段没有限制,只要该字段是数据表的某一字段即可。 查询结果以多表的形式返回,如果查询结果为空 (查询的数据在数据库中找不到) ,就返回空列表。

查询操作:

操作说明

代码示例
全表查询, 等同于 SQL 语句 Select * from index_product,数据以列表形式返回 >>> p = Product.objects.all() 
>>> p[1].name 
' HUAWEI nova 2s ' 
查询前 5 条数据, 等同于 SQL 语句 Select * from index_product LIMIT 5 
SQL 语句里面的 LIMIT 方法, 在 Django 中使用 Python 的列表截取分解即可实现 
>>> p = Product.objects.all()[:5] 
查询某个字段, 等同于 SQL 语句 Select name from index product 
values 方法,以列表形式返回数据, 列表元素以字典格式表示 
>>> p = Product.objects.values('name') 
>>> p[1] ['name'] 
' HUAWEI nova 2s '
values list 方法,以列表表示返回数据,列表元素以元组格式表示 >>> p = Product.objects.values_list('name')[:3] 
>>> p 
<QuerySet [('荣耀 V10' ,),('HUAWEI nova 2s',),('荣耀 Waterplay')]>
使用 get 方法查询数据,等于同 SQL 语句 
Select * from index product where id=2 
>>> p = Product.objects.get(id = 2) 
>>> p.name 
' HUAWEI nova 2s ' 
SQL 的 and 查询主要在 filter 里面添加多个查询条件 >>> p = Product.objects.filter(name=' 华为荣耀 V9 ',id=9) 
>>> p 
<QuerySet [<Product : Product object (9)>]> 
使用 count 方法统计查询数据的数据量

>>> p = Product.objects.filter(name= ' 华为荣耀 V9 ' ).count()

>>> p

SQL 的 or 查询,需要引入 Q,编写格式: Q(field=value) IQ(field=value) 
等同于 SQL 语句 Select * from index product where name= ' 华为荣耀 V9 ' or id=9 
>>> from django.db.models import Q 
>>> p = Product.objects.filter(Q(name= '华为荣耀 V9') | IQ(id=9))

去重查询, distinct 方法无须设置参数,去重方式根据 values 设置的字段执行

等同 SQL 语句 Select DISTINCT name from index_product where name = ' 华为荣耀 V9 '

>>> p = Product.objects.values( ' name ' ).filter(name= ' 华为荣耀V9 ' ).distinct ()

>>> p

<QuerySet [{ ' name 川 ' 华为荣耀 V9 ' } ] > 

根据字段 id 降序排列, 降序只要在 order by 里面的字段前面加 "-" 即可 # order_by 可设置多字段排列,如 Product.objects.order_by( '-id’ , name ')

>>> p = Product.objects.order_by( ' -id' )

>>> p 

聚合查询, 实现对数据值求和、求平均值等。 Django 提供 annotate 和 aggregate 方法实现 

annotate 类似于 SQL 里面的 GROUP BY 方法, 如果不设置 values,就会默认对主键进行 GROUP BY 分组

等同于 SQL 语句 Select name, SUM(id) AS ' id sum' from index product GROUP BY name ORDER BY NULL

>>> from django.db.models import Sum, Count

>>> p = Product.objects.values(' name ') .annotate(Sum( ' id' ))

>>> print(p.query) 

aggregate 是将某个字段的值进行计算并只返回计算结果

等同于 SQL 语句 Select COUNT(id) AS ' id count ' from index_product

>>> from django.db .models import Count

>>> p = Product.objects.aggregate (id_count=Count ( 'id'))

>>> p

{' id count ' : 11} 

查询条件 filter 和 get 使用等值的方法来 匹配结果。 若想使用大于、不等于和模糊查询的匹配方法,则可以使用下表:

匹配符 使用 说明 
__exactfilter(name__exact= ' 荣耀')精确等于,如SQL的like '荣耀' 
__iexactfilter(name__iexact= ' 荣耀')精确等于并忽略大小写
__contamsfilter(name__contains= '荣耀')模糊匹配, 如SQL的like('%荣耀%' )
__icontalnsfilter(name__icontains='荣耀')模糊匹配,忽略大小写
__gtfilter(id__gt=5)大于
__gtefilter( id__gte=5)大于等于
__ltfilter(id__lt=5)小于 
__lte  filter(id__lte=5)小于等于
__infilter(id__in=[1,2,3])判断是否在列表内内
__startswithfilter(name__startswith='荣耀')以...开头 
__endswithfilter(name __endswith=' 荣耀')以...结尾 
__istartswithfilter(name__istartswith= '荣耀') 以...开头并忽略大小写 
__iendswithfilter(name__iendswith= '荣耀')以...结尾并忽略大小写
__rangefilter(name__range='荣耀')在....范围内
__yearfilter(date__year=2018)日期字段的年份
__monthfilter(date__month=12)日期字段的月份
__dayfilter( dat__day=30)日期字段的天数 
__isnullfilter(name__isnull=TruelFalse)判断是否为空

多表查询:

一对多或一对一的表关系是通过外键实现关联的,而多表查询分为正向查询和 反向查询。以模型 Product 和 Type 为例:

  • 如果查询对象的主体是模型 Type,要查询模型 Type 的数据,那么该查询称 为正向查询。
  • 如果查询对象的主体是模型 Type,要通过模型 Type 查询模型 Product 的数据, 那么该查询称为反向查询。
>>> t = Type.objects.filter(product_id=ll ) 
#正向查询 
>>> t <QuerySet [<Type: Type object (1)>]> 
>>> t[0].type_name 
' 手机 '
#反向查询 
>>> t[0].product_set.values('name') 
<QuerySet [{ ' name 勺 ' 荣耀 V工0 ' } , {' name 气 ' HUAWE工 nova 2s ' }, { ' name': 冒 华 为荣耀 V9 ' }, { ' name 勺 ' 华为荣耀 V9 ' } , { ' name 勺'华为荣耀 V9' } ] > 

正向查询在数据库中只执行了 一次 SQL 查询。而反向查询通过 t[0].product_set.values(' name') 来获取模型Product 的数据,因此反向查询执行了两次 SQL 查询, 首先查询模型 Type 的数据,然后根据第一次查询的结果再查询与模型 Product 相互关联的数据。

为了减少反向查询的查询次数,我们可以使用 select related 方法实现, 该方法只 执行一次 SQL 查询就能达到反向查询的效果。 select related 使用方法如下:

功能代码等同SQL语句
查询模型 Product 的字段 name 和模型 Type 的字段 type_name>>> Product.objects.select_related(' type ') .values( ' name ' , ' type__type_ name ')SELECT name, type_narne FROM index_product INNER JOIN index type ON (type_id = id) 
查询两个模型的全部数据 >>>Product.objects.select_related( ' type ' ).all() SELECT * FROM index_product INNER JOIN index_type ON (type_id = id) 
获取两模型数据,以模型 Type 的 type name 字段等于手机为查询条件>>> Product.objects.select_related(' type') .filter(type__type_name= '手机 ').all() SELECT * FROM index_product INNER JOIN inde_ type ON (type_id = id) WHERE index_type.type_name = , 手机 '

select related 的使用说明如下:

  • 以模型 Product 作为查询对象主体,当然也可以使用模型 Type,只要两表之间 有外键关联即可。
  • 设置 select_related的参数值为"type"该参数值是模型 Product定义的 type 字段。
  • 如果在查询过程中 需要使用 另 一个数据表的字段, 可以使用"外键 字段名 " 来指向该表的字段。如 type_ type_name 代表由模型 Product 的外键 type 指向 模型 Type 的字段 type_ name, type 代表模型 Product 的外键 type, 双下画线" __" 代表连接符, type_name 是模型 Type 的字段。

select_related 还可以支持三个或三个以上的数据表同时查询:

p = Person.objects.select_related('living__province').get(name='张三') 
p.living.province 

上例中的living和provine是俩个外键。通过双下划线"__”连接起来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值