Django ORM相关操作

摘要:
DjangoORM相关操作PythonDjangoORM在Python脚本中调用Django环境很多情况下,在做测试的时候需要在Python脚本进行,此时若想成功运行需要导入Django环境配置,否则运行不成功。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。
Django ORM相关操作
PythonDjangoORM

在Python脚本中调用Django环境

很多情况下,在做测试的时候需要在Python脚本进行,此时若想成功运行需要导入Django环境配置,否则运行不成功。

import os

if __name__ == '__main__':
    # 导入配置环境,记不住就去manage.py中找
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ormday69.settings")
    # 启动Django
    import django
    django.setup()

    # 要进行的操作
    from app01 import models
    .....
    

Django终端打印SQL语句

在运行相应的操作后会在终端打印相应的SQL语句
在Django项目的settings.py文件中,在最后复制粘贴如下代码:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

一般操作

基本的语法是:models.类名.objects.函数名()

必知必会13个

all()

  1. 功能:
    查询表中的所有结果
  2. 使用方式:
    models.Person.objects.all()
  3. 返回内容:
    QuerySet

get()

  1. 功能:
    返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
  2. 使用方式:
    models.Person.objects.get(id=1)
  3. 返回内容:
    Object

filter(**kwargs)

  1. 功能:
    返回所给筛选条件相匹配的对象,返回的是个类似于列表一样的QuerySet对象。如果没有找到不会报错,会返回一个空的QuerySet对象,及时只有一个返回值照样返回QuerySet,想要取到某一个值可以使用索引。

  2. 使用方式:

    ret = models.Person.objects.filter()
    
    ret = models.Person.objects.filter()
    ret[0]
    
  3. 返回内容:
    QuerySet

注意比较get方法和filter方法的不同之处

exclude(**kwargs)

  1. 功能:
    与所给筛选条件不匹配的对象
  2. 使用方式:
    ret = models.Person.objects.exclude(id=1)
  3. 返回内容:
    QuerySet

values(*field)

  1. 功能:
    返回一个可迭代的字典序列,每一个都是 {"字段":值} 的形式
    参数为数据表的字段,如果没有字段则返回所有字段
  2. 使用方式:
    ret = models.Person.objects.values()
  3. 返回内容:
    特殊的QuerySet

values_list(*field)

  1. 功能:
    它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
  2. 使用方式:
    ret = models.Person.objects.values_list()
  3. 返回内容:
    特殊的QuerySet

order_by(*field)

  1. 功能:
    对查询结果排序
    1. 有参数,按照参数字段排序

    2. 没有参数,类在元数据中设置了默认排序方式
      按照元数据的默认排序方式,元数据设置方式如下:

      class Person(models.Model):
          name = models.CharField(max_length=32)
          age = models.IntegerField(default=18)
          birthday = models.DateField(auto_now_add=True)
      
          def __str__(self):
              return "<Object:Person>{}".format(self.name)
      
          class Meta:
              ordering=("birthday", )
      
    3. 没有参数,且没有设置元数据
      按照原有顺序输出,不排序

  2. 使用方式:
    ret = models.Person.objects.order_by()
  3. 返回内容:
    QuerySet

reverse()

  1. 功能:
    对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。
  2. 使用方式:
    ret = models.Person.objects.reverse()
  3. 返回内容:
    QuerySet

count()

  1. 功能:
    返回数据库中匹配查询(QuerySet)的对象数量。
  2. 使用方式:
    ret = models.Person.objects.count()
  3. 返回内容:
    数字

first()

  1. 功能:
    返回第一条记录
  2. 使用方式:
    ret = models.Person.objects.first()
  3. 返回内容:
    具体的对象

last()

  1. 功能:
    返回最后一条记录
  2. 使用方式:
    ret = models.Person.objects.last()
  3. 返回内容:
    具体的对象

exists()

  1. 功能:
    如果QuerySet包含数据,就返回True,否则返回False
  2. 使用方式:
    ret = models.Person.objects.exists()
  3. 返回内容:
    布尔值

distinct()

  1. 功能:
    从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。)

  2. 使用方式:

  3. 返回内容:

单表查询之神奇的双下划线

只能用在前面提到的filter函数中使用,方式为:字段+双下划线+=+值

__lt __gt

models.Person.objects.filter(id__gt=2, id__lt=5) # 获取 id 大于 2 且小于 5 的值

__in

models.Person.objects.filter(id__in=[1, 2, 3]) # 获取 id 等于 11、22、33 的数据

models.Person.objects.exclude(id__in=[1, 2, 3]) # 获取 id 不等于 11、22、33 的数据

__contains

models.Person.objects.filter(name__contains="ban") # 获取 name 字段包含 "ban" 的

models.Person.objects.filter(name__icontains="ban") # icontains 对大小写不敏感

__range

models.Person.objects.filter(id__range=(1, 3)) # id 范围是 1 到 3 的,等价于 SQL 的 bettwen and

date字段有:__year, __month, __day

models.Person.objects.filter(birthday__day=6) # 表示 birthday 字段中日为 6

其他关于字符串的还有

startswith,istartswith, endswith, iendswith

ForeignKey操作

正向查找

  1. 对象查找(跨表)
    语法:

    对象.关联字段.字段

    示例:

    book_obj = models.Book.objects.first()  # 第一本书对象
    print(book_obj.publisher)  # 得到这本书关联的出版社对象
    print(book_obj.publisher.name)  # 得到出版社对象的名称
    
  2. 字段查找(跨表)
    根据双下划线跨表查询,双下划线就代表跨了一张表
    语法:

    关联字段__字段

    示例:

    print(models.Book.objects.values_list("publisher__name"))
    

反向查询

  1. 对象查找
    语法:

    obj.表名_set

    示例:

    publisher_obj = models.Publisher.objects.first()  # 找到第一个出版社对象
    books = publisher_obj.book_set.all()  # 找到第一个出版社出版的所有书
    titles = books.values_list("title")  # 找到第一个出版社出版的所有书的书名
    
  2. 字段查找
    语法:

    表名__字段

    示例:

    titles = models.Publisher.objects.values_list("book__title")
    

注意:

操作方面
操作方面
类方面
类方面

ManyToManyField

class RelatedManager

"关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。

它存在于下面两种情况:

  1. 外键关系的反向查询
  2. 多对多关联关系

简单来说就是当 点后面的对象 可能存在多个的时候就可以使用以下的方法。

方法

create()

创建一个新的对象,保存对象,并将它添加到关联对象集之中,返回新创建的对象。

# step1:在book表中创建了一本新书,step2:在作者和书的关系表中添加关联记录
author_obj.books.create(title="跟金老板学开坦克", publisher_id=2)

add()

把指定的model对象添加到关联对象集中。
添加对象

book_obj = models.Book.objects.get(id=7)
author_obj.books.add(book_obj)

添加对象列表

book_objs = models.Book.objects.filter(id__gt=9)
author_obj.books.add(*book_objs)    # 要把列表打散再传进去

添加id

author_obj.books.add(12)

set()

更新model对象的关联对象。

book_obj = models.Book.objects.first()
book_obj.authors.set([2, 3])

remove()

从关联对象集中移除执行的model对象

book_obj = models.Book.objects.first()
book_obj.authors.remove(3)

clear()

从关联对象集中移除一切对象。

book_obj = models.Book.objects.first()
book_obj.authors.clear()

注意:

  1. 对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。
  2. 对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法

聚合查询和分组查询

聚合

aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。

用到的内置函数:

from django.db.models import Avg, Sum, Max, Min, Count

键的名称是聚合值的标识符,值是计算出来的聚合值。
1. 键的名称是按照字段和聚合函数的名称自动生成出来的。[字段名__函数名]

models.Book.objects.all().aggregate(Avg("price"))

键的名称:price__avg

2. 如果你想要为聚合值指定一个名称,可以向聚合子句提供它。

models.Book.objects.all().aggregate(avg_price=Avg("price"))

键的名称:avg_price

3. 如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。

如果你也想知道所有图书价格的最大值和最小值,可以这样查询:

models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price"))

分组

假设现在有一张公司职员表:

Django ORM相关操作第3张

按照部分分组求平均工资

  1. 原生SQL语句
    select dept,AVG(salary) from employee group by dept;
    
  2. ORM
    from django.db.models import Avg
    Employee.objects.values("dept").annotate(avg=Avg("salary").values(dept, "avg")
    

连表查询的分组

  1. 原生SQL语句
    select dept.name,AVG(salary) from employee inner join dept on (employee.dept_id=dept.id) group by dept_id;
    
  2. ORM
    from django.db.models import Avg
    models.Dept.objects.annotate(avg=Avg("employee__salary")).values("name", "avg")
    

更多示例

  1. 查询每一本书的作者个数
ret = models.Book.objects.all().annotate(author_num=Count("author"))
print(ret.author_num) # ret是列表,不能对其使用.属性
for book in ret:
   print("书名:{},作者数量:{}".format(book.title, book.author_num))
  1. 查询作者数量大于一的书
ret=models.Book.objects.all().annotate(author_num=Count("author")).filter(author_num__gt=1)
    print(ret[0].title)
  1. 查询各个作者出的书的总价格
ret=models.Author.objects.all().annotate(price_num=Sum("books__price")).values_list("name", "price_num")
ret=models.Author.objects.all().annotate(price_num=Sum("books__price")).values("name", "price_num")
print(ret.values_list("id", "name", "price_num"))
print(ret)
for i in ret:
    print(i.get("name"), i.get("price_num"))

F查询和Q查询

F查询

Django 提供 F() 对两个字段的值做比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

示例

  1. 查询库存数大于卖出数的所有书(两个字段作比较)
from django.db.models import F
ret = models.Book.objects.filter(kucun__gt=F("maichu"))
for book in ret:
    print(book.title, book.kucun, book.maichu)
  1. 刷单 把每一本书的卖出数都乘以3
# 单个对象操作用save
# obj = models.Book.objects.first()
# obj.maichu = 100 * 3
# obj.save()

# 具体的对象没有 update(), QuerySet 对象才有 update() 方法
models.Book.objects.update(maichu=(F("maichu")+1)*3)
  1. 给每一本书的书名后面加上 第一版
from django.db.models.functions import Concat
from django.db.models import Value

models.Book.objects.update(title=Concat(F("title"), Value("第一版")))

Q查询

filter() 等方法中的关键字参数查询都是一起进行 “AND” 的。 如果你需要执行更复杂的查询(例如 OR 语句),你可以使用 Q 对象。

from django.db.models import Q
# 查询 卖出数大于1000,并且 价格小于100的所有书
ret = models.Book.objects.filter(maichu__gt=1000, price__lt=100)
print(ret)
# 查询 卖出数大于1000,或者 价格小于100的所有书
ret = models.Book.objects.filter(Q(maichu__gt=1000) | Q(price__lt=100))

可以组合 & 和 | 操作符以及使用括号进行分组来编写任意复杂的 Q 对象。同时,Q 对象可以使用 ~ 操作符取反,这允许组合正常的查询和取反 (NOT) 查询。

查询函数可以混合使用 Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或 Q 对象)都将 "AND" 在一起。但是,如果出现 Q 对象,它必须位于所有关键字参数的前面。

# Q查询和字段查询同时存在时, 字段查询要放在Q查询的后面
ret = models.Book.objects.filter(Q(maichu__gt=1000) | Q(price__lt=100), title__contains="金老板")
print(ret)

事务

原子性操作: 中间一旦某个环节出了问题,则整个操作都将取消,包括出错环节之前已经执行过的环节。

try:
    from django.db import transaction
    with transaction.atomic():
        new_publisher = models.Publisher.objects.create(name="火星出版社")
        models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10)  # 指定一个不存在的出版社id
except Exception as e:
    print(str(e))

参考:https://www.cnblogs.com/liwenzhou/p/8660826.html

Django ORM相关操作第4张

免责声明:文章转载自《Django ORM相关操作》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇WPF多语言功能简单示例一个消息调度框架构建下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

8. Django系列之上传文件与下载-djang为服务端,requests为客户端

preface 运维平台新上线一个探测功能,需要上传文件到服务器上和下载文件从服务器上,那么我们就看看requests作为客户端,django作为服务器端怎么去处理? 对于静态文件我们不建议通过django下载,而是建议通过django返回一个重定向URL(下载文件的URL)给client,这个url是nginx提供下载,众所周知,nginx是非常牛逼的静...

Django项目中使用celery做异步任务

异步任务介绍 在写项目过程中经常会遇到一些耗时的任务, 比如:发送邮件、发送短信等等~。这些操作如果都同步执行耗时长对用户体验不友好,在这种情况下就可以把任务放在后台异步执行 celery就是用于处理异步任务的框架,celery能完成的功能远不止异步任务,还有一个很常用的功能定时任务 架构图 Celery包含如下组件: Celery Beat:任务调度...

Django文件上传(经典上传方式)

经典文件上传方式 创建URL from django.contrib importadmin from django.urls importpath from django.conf.urls importurl from app01 importviews urlpatterns =[ path('admin/', admin.site...

django 框架模型之models常用的Field

django 框架模型之models常用的Field,这些Field的参数、及常见错误原因及处理方案。 1. django 模型models 常用字段 1、models.AutoField   自增列 = int(11) 如果没有的话,默认会生成一个名称为 id 的列 如果要显式的自定义一个自增列,必须设置primary_ke...

【Python】Celery异步处理

参考:http://www.cnblogs.com/znicy/p/5626040.html 参考:http://www.weiguda.com/blog/73/ 参考:http://blog.csdn.net/iloveyin/article/details/44940931 django、celery、django-celery、kombu、amqp最...

Django 多对多中间表详解

一、默认中间表  首先,模型是这样的: class Person(models.Model): name = models.CharField(max_length=128) def __str__(self): return self.name class Group(models.Model): name...