django orm


1.查看orm执行的sql

In [1]: from cost_app.models import AccountInfo                                                                                                                                              

In [2]: print(str(AccountInfo.objects.all().query))                                                                                                                                          
SELECT "account_info"."id", "account_info"."name", "account_info"."platform", "account_info"."company" FROM "account_info"

2.返回查询集的API

可以参考 https://www.cnblogs.com/rangger/p/9801165.html

https://www.jianshu.com/p/380aa2f6c88e

方法名 解释
filter()    过滤查询对象。
exclude()   排除满足条件的对象
annotate()  使用聚合函数
order_by()  对查询集进行排序
reverse()   反向排序
distinct()  对查询集去重
values()    返回包含对象具体值的字典的QuerySet
values_list()   与values()类似,只是返回的是元组而不是字典。
dates()     根据日期获取查询集
datetimes()     根据时间获取查询集
none()  创建空的查询集
all()   获取所有的对象
union()     并集
intersection()  交集
difference()    差集
select_related()    附带查询关联对象
prefetch_related()  预先查询
extra()     附加SQL查询
defer()     不加载指定字段
only()  只加载指定的字段
using()     选择数据库
select_for_update()     锁住选择的对象,直到事务结束。
raw()   接收一个原始的SQL查询
  • exclude()
# 下面的示例排除所有pub_date晚于2005-1-3且headline为“Hello” 的记录:
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')
#下面的示例排除所有pub_date晚于2005-1-3或者headline 为“Hello” 的记录:
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')
  • values()
# values(fields, *expressions)
# 返回一个包含数据的字典的queryset,而不是模型实例。
# 每个字典表示一个对象,键对应于模型对象的属性名称。
# 下面的例子将values() 与普通的模型对象进行比较:

# 列表中包含的是Blog对象
>>> Blog.objects.filter(name__startswith='Beatles')
<QuerySet [<Blog: Beatles Blog>]>
# 列表中包含的是数据字典
>>> Blog.objects.filter(name__startswith='Beatles').values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>



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

#values()方法还有关键字参数**expressions,这些参数将传递给annotate():

>>> from django.db.models.functions import Lower
>>> Blog.objects.values(lower_name=Lower('name'))
<QuerySet [{'lower_name': 'beatles blog'}]>

# 在values()子句中的聚合应用于相同values()子句中的其他参数之前。 如果需要按另一个值分组,请将其添加到较早的values()子句中。 像这样:

>>> from django.db.models import Count
>>> Blog.objects.values('author', entries=Count('entry'))
<QuerySet [{'author': 1, 'entries': 20}, {'author': 1, 'entries': 13}]>
>>> Blog.objects.values('author').annotate(entries=Count('entry'))
<QuerySet [{'author': 1, 'entries': 33}]>
  • dates()
>>> Entry.objects.dates('pub_date', 'year')
[datetime.date(2005, 1, 1)]
>>> Entry.objects.dates('pub_date', 'month')
[datetime.date(2005, 2, 1), datetime.date(2005, 3, 1)]
>>> Entry.objects.dates('pub_date', 'day')
[datetime.date(2005, 2, 20), datetime.date(2005, 3, 20)]
>>> Entry.objects.dates('pub_date', 'day', order='DESC')
[datetime.date(2005, 3, 20), datetime.date(2005, 2, 20)]
>>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day')
[datetime.date(2005, 3, 20)]
  • datetimes()

3.不返回查询集的API

  • 增删改查对象

  • 统计记录

  • 聚合

  1. 自关联
  • 一对一自关联
#评论表
class Comment(models.Model):
    #评论的内容字段
    content=models.CharField(max_length=255)
    #评论的发布时间
    push_time=models.DateTimeField(auto_now_add=True)
    #关联父评论的id,可以为空
    pcomment = models.ForeignKey(to='self',null=True) 
    def __str__(self):
        return self.content
  • 多对多自关联
class Person(models.Model):
    name = models.CharField(max_length=12)
    #人和人交朋友
    friends = models.ManyToManyField(to='self',symmetrical=False,related_name='ship')
    def __str__(self):
        return self.name

5.常用的表元数据

class Books(models.Model):
        """图书类"""
        name = models.CharField(max_length=20)
        price = models.PositiveSmallIntegerField()
        word_num = models.PositiveIntegerField()

        class Meta:
            abstract = True  # 当该参数设置为True时表示该模型类是一个基类,提供给其他模型类继承,因此该基类不会在数据库中生成数据表。
            app_label = "app_name"  # 该参数是用于当我们没有在INSTALLED_APPS中注册app时,需要用该参数来说明该模型类属于哪个app。
            db_table = "books"  # 该参数表示该模型类在数据库中生成的数据表的表名。
            get_latest_by = "price"  # 该参数定义了当我们使用latest()和earliest()方法时是通过什么字段来进行排序的。
            managed = True  # 该参数默认值为True,表示Django将按照既定的规则,管理数据库表的生命周期。如果设置为False,将不会针对当前模型创建和删除数据库表.
            ordering = ["price"]  # 该参数表示按照什么字段排序,目前表示按照price升序排序,如需要降序,则在字段名前加一个负号["-price"],同时可以添加多个排序选项,如["price", "word_num"]表示先按照price升序排序,然后price相同的再按照word_num升序排序。
            permissions = (("allow_update", "允许更新图书"),)  # 该参数用于当创建对象时增加额外的权限。它接收一个所有元素都是二元元组的列表或元组,每个元素都是(权限代码, 直观的权限名称)的格式
            indexes = [models.Index(fields=['name', 'price']), ]  # 该参数表示要在模型上定义的索引列表,用于在数据库中创建索引。
            unique_together = (("name", "price"),)  # 该参数表示联合唯一约束,参数值可以是一维的,也可以是二维的,我这里是用二维的举例,当前表示该表中不能出现name和price都相同的书籍出现,该参数可以设置多组联合唯一约束,另外,如果约束只有一组的情况下可以用一维表示。
            verbose_name = "图书"  # 该参数可以设置模型直观的名称,一般我们设置为中文,如果不设置,那么Django会默认使用小写的模型名。
            verbose_name_plural = verbose_name  # 该参数是verbose_name的复数形式,由于中文没有复数的概念,所以一般verbose_name_plural = verbose_name。
  1. F查询

    # Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
    查询书id大于\小于价格的书籍
    1 models.Book.objects.filter(id__gt=F("price"))
    2 <QuerySet []>
    3 
    4 models.Book.objects.filter(id__lt=F("price"))
    5 <QuerySet [<Book: 书一>, <Book: 书二>, <Book: 书三>, <Book: 书四>, <Book: 书五>, <Book: 书六>]>
    Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。 
    1 models.Book.objects.filter(id__lt=F("price")/2)
    2 <QuerySet [<Book: 书一>, <Book: 书二>, <Book: 书三>, <Book: 书四>, <Book: 书五>]>
    修改操作也可以使用F函数,比如将每一本书的价格提高30
    models.Book.objects.all().update(price=F("price")+30)
    字符串使用Concat连接
    from django.db.models.functions import Concat
    from django.db.models import Value
    models.Book.objects.update(title=Concat(F("title"),Value("("),Value("第"),Value(")")))
    
  2. Q查询

>>> from django.db.models import Q
# Q(...)
>>> Question.objects.filter(Q(question_text__contains='you'))
[<Question: what are you doing>, <Question: what is wrong with you>, <Question: who are you>]
# Q(...), Q(...)
>>> Question.objects.filter(Q(question_text__contains='you'), Q(question_text__contains='what'))
[<Question: what are you doing>, <Question: what is wrong with you>]
# Q(...) & Q(...)
>>> Question.objects.filter(Q(question_text__contains='you') & Q(question_text__contains='what'))
[<Question: what are you doing>, <Question: what is wrong with you>]