58.2-Django模型之查询集切片过滤器

2020-08-12  本文已影响0人  BeautifulSoulpy

总结:

  1. 查询管理器一般至少定义一个 才可以查询;
  2. 浏览器端发来的数据都不可信;
  3. 结果集本身就是一个 缓存 ;
  4. _str_ 是给用户看的,_repr_则是给开发者看的;例如:
    str(dog) 'i am kitty'
    repr(dog) 'Animal:name is kitty'
  5. 字段命名 禁止使用__;

模型操作

管理器对象

Django会为模型类提供一个objects对象,它是django.db.models.manager.Manager类型,用于与数据库交互(对数据库进行 增删改查)。

Django 的一个强大的功能是它的对象关系映射Object-Relational Mapper(ORM),它允许你就像使用 SQL 一样去和你的数据库交互。事实上,Django 的 ORM 就是创建 SQL 去查询和操作数据库的一个 Python 式方式,并且获得 Python 风格的结果。 我说的是一种方式,但实际上,它是一种非常聪明的工程方法,它利用了 Python 中一些很复杂的部分,而使得开发者更加轻松。

当定义模型类的时候没有指定管理器,则Django会为模型类提供一个objects的管理器。
如果在模型类中手动指定管理器后,Django不再提供默认的objects的管理器了。
管理器是Django的模型进行数据库查询操作的接口,Django应用的每个模型都至少拥有一个管理器。

Django ORM

数据的校验validation是在对象的Save、update方法上


1. 查询

1.1 查询集

查询会返回结果的集, 它是django.db.models.query.Query Set类型。
它是惰性求值, 和sql alchemy一样。结果就是查询的集。
它是可迭代对象。

# blog/user/urls  # 设置访问路劲;
from django.conf.urls import url
from .views import reg,show

urlpatterns = [
    url(r'^reg$',reg),
    url(r'^show$',show)
    ]

# blog/user/show  中增加 
def show(request):          # 方法的使用方式各不相同;
    query = User.objects.all()   # objects

    return JsonResponse({})
#-------------------------------------------------------
{}

1、惰性求值:
创建查询集不会带来任何数据库的访问,直到调用方法使用数据时,才会访问数据库。在迭代、序列化、if语句中都会立即求值。

2、缓存:
每一个查询集都包含一个缓存,来最小化对数据库的访问。

新建查询集,缓存为空。首次对查询集求值时,会发生数据库查询,Django会把查询的结果存在这个缓存中,并返回请求的结果,接下来对查询集求值将使用缓存的结果。

观察下面的2个例子是要看真正生成的语句了

  1. 没有使用缓存,每次都要去查库,查了2次库
    [user.name for user in User.objects.all()]
    [user.name for user in User.objects.all()]
[u for u in User.objects.all()]
[u for u in User.objects.all()]
  1. 下面的语句使用缓存,因为使用同一个结果集,查一遍;
    qs = User.objects.all()
    [user.name for user in qs]
    [user.name for user in qs]
    [u for u in users] # 查一遍
    [u for u in users]
1.2 限制查询集(切片)

为了不对数据库多次查询,
http://127.0.0.1:8000/admin/user/user/ 增加2个用户

查询集对象可以直接使用索引下标的方式(不支持负索引),相当于SQL语句中的limit和offset子句。
注意使用索引返回的新的结果集,依然是惰性求值,不会立即查询。

qs = User.objects.all()[20:40]
# LIMIT 20 OFFSET 20

users = User.objects.all()[1:]
print(users)# objects
#---------------------------------------
<QuerySet [<User 6 jerry>, <User 7 ben>]>
1.3 过滤器

返回查询集的方法,称为过滤器,如下:
User.objects.-------

名称 说明
all()
filter() 过滤,返回满足条件的数据
exclude() 排除,排除满足条件的数据
order_by()
values() 返回一个对象字典的列表,列表的元素是字典,字典内是字段和值的键值对

filter(k1=v1).filter(k2=v2) 等价于 filter(k1=v1, k2=v2)
filter(pk=10) 这里pk指的就是主键, 不用关心主键字段名,当然也可以使用使用主键名filter(emp_no=10) 返回单个值的方法

// 
users = User.objects.all()
print(users.values())# objects
# ------------------------------------------------------------------
<QuerySet [{'id': 1, 'name': 'tom', 'email': 'tom@magedu.com', 'password': 'tom'}, {'id': 6, 'name': 'jerry', 'email': 'jerry@magedu.com', 'password': 'jerry'}, {'id': 7, 'name':
 'ben', 'email': 'ben@a.com', 'password': 'ben'}]>
名称 说明
get() 仅返回单个满足条件的对象
如果未能返回对象则抛出DoesNotExist异常;如果能返回多条,抛出MultipleObjectsReturned异常
count() 返回当前查询的总条数
first() 返回第一个对象
last() 返回最后一个对象
exist() 判断查询集中是否有数据,如果有则返回True
user = User.objects.filter(email=email).get() # 期待查询集只有一行,否则抛出异常
user = User.objects.get(pk=2) # 返回不是查询集,而是一个User实例,否则抛出异常
user = User.objects.get(id=1) # 更多的查询使用主键,也可以使用pk=1
user = User.objects.first() # 使用limit 1查询,查到返回一个实例,查不到返回None
user = User.objects.filter(pk=3, email=email).first() # and条件
1.4 字段查询(Field Lookup)表达式

字段查询表达式可以作为filter()、exclude()、get()的参数,实现where子句。
语法: 属性(字段)名称__比较运算符=值
注意:属性名和运算符之间使用双下划线
比较运算符如下

名称 举例 说明
exact filter(is deleted=False)
filter(is deleted_ _exact=False)
严格等于,可省略不写
contains exclude(title__contains='天') 是否包含,大小写敏感,等价于like'%天%'
statswith
endswith
filter(title__starts with='天' 以什么开头或结尾,大小写敏感
isnull
isnotnull
filter(title__is null=False) 是否为null
iexact
icontains
istartswith
i ends with
i的意思是忽略大小写
in filter(pk_in=[1, 2, 3, 100] ) 是否在指定范围数据中
gt、gte 大
It、Ite 小
filter(id__gt=3)
filter(pk__lte=6)
filter(pub_date__gt=date(2000, 1, 1) )
大于、小于等
year、month、day
week_day
hour、minute、second
filter(pub_date__year=2000) 对日期类型属性处理
1.5 Q对象

虽然Django提供传入条件的方式,但是不方便,它还提供了Q对象来解决。
Q对象是django.db.models.Q,可以使用&(and)、|(or)操作符来组成逻辑表达式。 ~ 表示not。

from django.db.models import Q
User.objects.filter(Q(pk__lt=6)) # 不如直接写User.objects.filter(pk<6)
User.objects.filter(pk__gt=6).filter(pk_lt=10) # 与
User.objects.filter(Q(pk_gt=6) & Q(pk_lt=10)) # 与
User.objects.filter(Q(pk=6) | Q(pk=10)) # 或
User.objects.filter(~Q(pk__lt=6)) # 非

可使用&|和Q对象来构造复杂的逻辑表达式
过滤器函数可以使用一个或多个Q对象
如果混用关键字参数和Q对象,那么Q对象必须位于关键字参数的前面。所有参数都将and在一起

上一篇下一篇

猜你喜欢

热点阅读