原文:https://docs.djangoproject.com/en/2.0/ref/models/querysets/
相关文章:https://blog.csdn.net/youyou1543724847/article/details/86425408
在创建QuerySet后,对QuerySet 进行filter、slice、传递操作,但是这些操作并不会立即导致相关SQL的执行。只有当对Query Set进行evaluate操作时,才会导致操作落库。
什么操作导致Query Set evaluated呢?
for e in Entry.objects.all():
print(e.headline)
PS:当你只需要确认Query Set中是否存储数据时(而不需要知道具体数据内容,请使用exist函数(该种方式比迭代访问更快),例如:
if some_queryset.filter(pk=entry.pk).exists():
print("Entry contained in queryset")
entry_list = list(Entry.objects.all())
if Entry.objects.filter(headline="Test"):
print("There is at least one Entry with the headline Test")
当你对一个Query set对象进行序列化时,会导致queryset 操作落库,且查询出来的数据都加载到内存中。通常来说,序列化是进行cache 操作的前序操作。另外当你对一个Query Set 进行反序列化时,你可以获取到对该QuerySet序列化时数据库的相关状态(例如,在对Query set序列化时,model中含有3条符合条件的数据,之后,model进行了其他的增删改查操作。但是当你反序列化后,得到的Query Set对象还是和之前的3条数据绑定了)。
如果你只想对Queryset 中的必要信息进行序列化(方便之后能重新构建出一个新的Queryset,而不需要绑定的数据),则可以只对Query Set对象的query属性进行处理(You can then recreate the original QuerySet (without any results loaded) 。
例如:
>>> import pickle
>>> query = pickle.loads(s) # Assuming 's' is the pickled string.
>>> qs = MyModel.objects.all()
>>> qs.query = query # Restore the original 'query'.
特点:
下面主要对QuerySet API进行简单描述。
API | 参数说明 | 含有 |
---|---|---|
filter(**kwargs) | kwargs 为 域查询参数(field lookup) | 返回包含满足条件对象的QuerySet 对象 。当存储多个查询参数时,参数通过and 相连 |
exclude(**kwargs) | kwargs 为 域查询参数(field lookup) | 返回包含 不满足条件对象的QuerySet 对象。当存储多个查询参数时,参数通过and 相连,然后在外面用一个not 扩起来,形如: where not ( A and B and C) |
annotate(*args, **kwargs) | 数据库聚合操作(sun,average等),详细信息见:https://docs.djangoproject.com/en/2.0/ref/models/querysets/#id5 | |
order_by(*fields) | 用于排序的字段 | 通常来说,在model meta中指定了排序的信息。但是可以通过order_by 对每个QuerySet进行排序定制 。例如:Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline') 。其中,字段前面的负号指示递减排序。递增是默认选项。如果要随机排序,使用?号。同时,order_by 支持多表的排序 |
reverse() | 对结果进行逆序。两次reverse之后,结果和原始的顺序一致 | |
distinct(*fields) | 字段名 | 去除重复的行 |
values(*fields, **expressions) | 返回一个Query Set,该Queryset evaluate 之后,返回的是一个字典(一般来说,QuerySet evaluate返回的是model 实例对象),该方法用于抽取model 记录中的部分字段,优点就是减少了构建python model 实例的花销. | |
values_list(*fields, flat=False, named=False) | 和values类似,但是Query Set中包含的是满足条件的元组列表。但flat=true时,直接返回Query Set,该queryset表示满足条件的元素列表 | |
dates(field, kind, order=‘ASC’) | ||
datetimes(field_name, kind, order=‘ASC’, tzinfo=None) | ||
none() | ||
all() | 返回一个当前QuerySet中一个 copy。当对该QuerySet进行了evaluate后,结果会在内存中缓存。当在evaluate后,数据库中的数据更新了,则可以再次调用QuerySe.all方法,更新缓存 | |
union(*other_qs, all=False) | 合并多个Query Set,即SQL中的union操作 | |
dintersection(*other_qs) | ||
difference(*other_qs) | 多个Query set进行比较,返回只存在当前Query Set中的元素 | |
select_related(*fields) | 在查询本model的满足条件的数据记录时,也会将相关的(其他model 表)的数据查询出来。并且,会将查询进行合并,减少SQL执行次数。扩展查询主要针对Foreign key 和 OneToOneField | |
prefetch_related(*lookups) | 返回一个QuerySet,该QuerySet会一次性的获取相关的对象信息(非一条SQL),但是多条SQL是一次性执行的。和select_related功能类似,但是实现策略不同。select_related是通过join语句实现的,因此,能在一条SQL中查询出所有相关的数据,缺点就是如果join的数据表数据很大,则join效率很低。prefetch_select 是通过每次搜索一条关系,使用Python自己做“join” | |
extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None) | 描述复杂的sql 语句。old API,尽量不要使用。 | |
defer(*fields) | ||
defer(*fields) | 当model数据项过多时,且你并不需要这个所有的字段,使用defer进行刷选,去掉fields指定的字段。当某些字段没有获取到后,以后需要访问时,会再次触发新的SQL语句 | |
only(*fields) | 和defer类似,但是fields 指定是需要留下的(返回的是一个Query Set,该Query Set表示满足条件的model实例列表,但是实例中的数据不全,有的字段没有填充获取 | |
using(alias) | 指定QuerySet对应的数据库 | |
select_for_update(nowait=False, skip_locked=False, of=()) | 返回一个Query Set,该Query Set 会锁定数据库中的相关的行,直到事务完成 | |
raw(raw_query, params=None, translations=None) | 用于执行Raw SQL语句,详情见:https://docs.djangoproject.com/en/2.0/topics/db/sql/ |
举例:
操作如下;
In [50]: cs=q.choice_set.all()
In [60]: cs_dict=cs.values('choice_text','votes')
#返回的是一个QuerySet ,但是QuerySet中的每条记录都是一个dict 普通对象。如;{'choice_text': 'not null', 'votes': 0}
In [61]: cs_dict
Out[61]:
In [58]: cs_list=cs.values_list('choice_text','votes')
#返回的是一个QuerySet ,但是QuerySet中的每条记录都是普通的元组
In [59]: cs_list
Out[59]:
#返回的是一个QuerySet,QuerySet中的每个元素都是一个model对象,只是这个对象的某些field没有填充。当获取这些没有填充的字段时,会触发SQL查询。
In [62]: cs_model=cs.only('choice_text')
In [63]: cs_model
Out[63]: , , , , , , ]>
模型定义如下:
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date pulbished')
def was_published_recently(self):
return self.pub_date >= timezone.now()
def __str__(self):
return "Question:%s" % self.question_text
class Choice(models.Model):
question = models.ForeignKey(Question,on_delete=models.CASCADE, null=True)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return "Choice:%s,%s" % (str(self.question), self.choice_text)
# This list contains a Blog object.
>>> Blog.objects.filter(name__startswith='Beatles')
]>
# This list contains a dictionary.
>>> Blog.objects.filter(name__startswith='Beatles').values()
>>> Entry.objects.values_list('id').order_by('id')
>>> Entry.objects.values_list('id', flat=True).order_by('id')
#普通的查询
# Hits the database.
e = Entry.objects.get(id=5)
# Hits the database again to get the related Blog object.
b = e.blog
# select_related
# Hits the database.
e = Entry.objects.select_related('blog').get(id=5)
# Doesn't hit the database, because e.blog has been prepopulated
# in the previous query.
b = e.blog
Blabla.objects.only('field1', 'field2', 'field3')[0].field4
#执行结果:通过一个新的SQL查询,获取field4的值。
Blabla.objects.values('field1', 'field2', 'field3')[0].field4
#执行结果:抛出异常。AttributeError: 'dict' object has no attribute 'field4'
class Q[source]
A Q() object, like an F object, encapsulates a SQL expression in a Python object that can be used in database-related operations.
In general, Q() objects make it possible to define and reuse conditions. This permits the construction of complex database queries using | (OR) and & (AND) operators; in particular, it is not otherwise possible to use OR in QuerySets.
https://docs.djangoproject.com/en/2.0/ref/models/expressions/#django.db.models.F
The following QuerySet methods evaluate the QuerySet and return something other than a QuerySet.These methods do not use a cache (see Caching and QuerySets). Rather, they query the database each time they’re called.
(每个Query Set 对象都有对应的cache区域。每个新建的QuerySet的cache 区域都是空的。当Query Set 被首次evaluate时,数据库操作落盘,Django会将结果放到该QuerySet的cache中,以后重用数据,例如迭代。另外,如果对QuerySet不是完整的evaluate,例如进行slice或是index,则结果不会进行缓存)
get(**kwargs): 返回满足条件的数据。当多条数据或没有数据时,都会抛错。kwargs为filed 查询参数。
create(**kwargs):创建对象并将对象保存到数据库中;
p = Person.objects.create(first_name="Bruce", last_name="Springsteen")
obj, created = Person.objects.get_or_create(
first_name='John',
last_name='Lennon',
defaults={'birthday': date(1940, 10, 9)},
)
等同于如下代码
try:
obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
obj.save()
>>> Blog.objects.in_bulk([1])
{1: }
>>> Blog.objects.in_bulk([1, 2])
{1: , 2: }
>>> Blog.objects.in_bulk([])
{}
>>> Blog.objects.in_bulk()
{1: , 2: , 3: }
>>> Blog.objects.in_bulk(['beatles_blog'], field_name='slug')
{'beatles_blog': }
https://docs.djangoproject.com/en/2.0/topics/db/queries/#lookups-that-span-relationships
Filed 查询参数格式形如:field__lookuptype=value。支持的lookuptype包括:
exact,iexact,contains,icontains,in,gt,gte,lt
lte,startswith,istartswith,endswith,iendswith,range,date,year,month,day,week,week_day,quarter,time,hour,minute,second,isnull,regex,iregex
注意:在字段查询中,field 必须是model 中定义的field。但是,如果某个字段是外建关联字段,则可以使用_id
。
也可以通过field lookup 进行多表之间的联合查询。
查询支持正向查询(本model 中包含关联关系字段)和反向查询(本model 中不包含关联关系字段)。
正向查询:
格式:‘本model的字段名’__'关联model中的字段名’
(注意:上面是双下划线)
另外,可以支持多级关联。多级关联时,直接在后面叠加。
例如:
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField()
def __str__(self):
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
n_comments = models.IntegerField()
n_pingbacks = models.IntegerField()
rating = models.IntegerField()
def __str__(self):
return self.headline
查询关联blog的名字为‘Beatles blog’的entry:
Entry.objects.filter(blog__name='Beatles Blog')
反向查询:
格式:’被关联的model的名称的小写‘__'被关联的model的field字段‘
例如:查询至少关联了一条headline 为“Lennon”的entry的所有blog。
Blog.objects.filter(entry__headline__contains='Lennon')
所有的聚合一般都有如下参数:
支持的聚合函数包括:
Q对象用于封装一个SQL表达式到一个Python 对象中。通过Q对象,可以构造一个的条件,如多个条件的or 和and。
Prefetch(lookup, queryset=None, to_attr=None):用于控制prefetch_related()的执行。
prefetch_related_objects(model_instances, *related_lookups)
FilteredRelation(relation_name, *, condition=Q()):用于在annotate 函数中,当执行join语句时,构建on 子句。