Django Queryset几个不常见的api

本文深入探讨了Django ORM中通过_set方法访问相关联表数据的机制,包括如何使用related_name优化访问方式,以及values和values_list用于获取数据的方式。同时,介绍了selected_related方法减少数据库查询次数,select_for_update确保并发操作时的数据一致性,bulk_create一次性创建多条记录,以及GT、GTE、LT、LTE查询操作符的使用。此外,文章还详细解释了在使用Date查询DateTimeField范围时的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、related_name
django还有一种通过对象访问相关联表数据的方法,即用_set。但是这种方法只能是相关类访问定义了关系的类(主键类访问外键类)。

class Blog(models.Model):
    pass

class Entry(models.Model):
    blog = models.ForeignKey(Blog)

如:b.entry_set.all() #b是一个blog对象

另外还有就是如果Entry中blog属性的定义如果改成这样:blog=models.ForeignKey(Blog,related_name='entries')这样的话就可以像下面这样通过blog对象得到entry对象的一个集合:


b=Blog.objects.get(id=1) b.entries.all() #==b.entry_set.all()# b.entries is a Manager that returns QuerySets. b.entries.filter(headline__contains='Lennon') b.entries.count()

2、values和values_list
返回的类似列表和字典的形式

Blog.objects.values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}],
Blog.objects.values('id', 'name')
[{'id': 1, 'name': 'Beatles Blog'}]

3、selected_related()
使用selected_related()的时候会自动的查询相关的外键的关系,这样可能会减少数据库查询的次数。

#查询数据库
e = Entry.objects.get(id=5)
#会再次查询数据库
b = e.blog

#查询数据库
e = Entry.objects.select_related().get(id=5)
#不会查询数据库了
b = e.blog

参考
https://docs.djangoproject.com/en/1.6/ref/models/querysets/#django.db.models.query.QuerySet.select_related

4、select_for_update
在部分大并发的时候,我们更新数据之前要先锁住记录,select_for_update就可以做到这个。

All matched entries will be locked until the end of the transaction block, meaning that other transactions will be prevented from changing or acquiring locks on them.

Usually, if another transaction has already acquired a lock on one of the selected rows, the query will block until the lock is released. If this is not the behavior you want, call select_for_update(nowait=True). This will make the call non-blocking. If a conflicting lock is already acquired by another transaction, DatabaseError will be raised when the queryset is evaluated.

Currently, the postgresql_psycopg2, oracle, and mysql database backends support select_for_update(). However, MySQL has no support for the nowait argument. Obviously, users of external third-party backends should check with their backend’s documentation for specifics in those cases.

Passing nowait=True to select_for_update() using database backends that do not support nowait, such as MySQL, will cause a DatabaseError to be raised. This is in order to prevent code unexpectedly blocking.

5、bulk_create
这个可以在一次数据库查询的时候创建多条记录

Entry.objects.bulk_create([
     Entry(headline="Django 1.0 Released"),
     Entry(headline="Django 1.1 Announced"),
     Entry(headline="Breaking: Django is awesome")
])

6、

gt
Greater than.

Example:

Entry.objects.filter(id__gt=4)
SQL equivalent:

SELECT ... WHERE id > 4;
gte
Greater than or equal to.

lt
Less than.

lte
Less than or equal to.

7、注意在使用Date查询DateTimeField的range的时候,不包括最后一天的。例如

import datetime
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))

这时候会生成这样的sql语句
SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';
如果里面的start_date等是DateTimeField的时候,就会产生这样的sql语句
SELECT ... WHERE pub_date BETWEEN '2005-01-01 00:00:00' and '2005-03-31 00:00:00';

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值