浅谈Django QuerySet对象(模型.objects)的常用方法

准备工作:

新建一个项目,在项目中新家一个app,名字自取。将app添加值settings.py中,然后配置settings连接数据库。

在app中的models中新建模型:

from django.db import models

# Create your models here.
class Author(models.Model):
  """作者模型"""
  name = models.CharField(max_length=100)
  age = models.IntegerField()
  email = models.EmailField()

  class Meta:
    db_table = 'author'

class Publisher(models.Model):
  """出版社模型"""
  name = models.CharField(max_length=300)

  class Meta:
    db_table = 'publisher'

class Book(models.Model):
  """图书模型"""
  name = models.CharField(max_length=300)
  pages = models.IntegerField()
  price = models.FloatField()  #书的定价
  rating = models.FloatField()
  author = models.ForeignKey(Author, on_delete=models.CASCADE)
  publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)

  class Meta:
    db_table = 'book'

class BookOrder(models.Model):
  """图书订单模型"""
  book = models.ForeignKey("Book", on_delete=models.CASCADE)
  price = models.FloatField()   #书卖出去的真正价格

  class Meta:
    db_table = 'book_order'

执行makemigrations后在migrate。

然后手动向表中添加数据,例如我添加的信息:

然后配置urls,直至项目运行成功。

1.filter:

过滤,将满足条件的数据提取出来,返回一个新的QuerySet。

2. exclude:

排除,排除满足条件的数据,返回一个新的QuerySet。

例如,取出book中id大于等于2的图书,并且id不能等于3的图书。示例代码:

books = models.Book.objects.filter(id__gt=1).exclude(id=3)

我们也可以使用Q表达式来实现,

from django.db.models import Q
books = models.Book.objects.filter(id__gt=1).filter(~Q(id=3))

3. annotate:

给QuerySet中的每个对象都添加一个使用查询表达式(聚合函数、F表达式、Q表达式、Func表达式等)的新字段。

例如 给每本图书都添加一个字段叫author_name

from django.db.models import F
books = models.Book.objects.annotate(author_name = F('author__name'))

注意:

Book模型下面最开始是没有author_name这个属性的。只有一个author属性连接的一个外键.

author__name是book下的author属性下的name,即book这个表通过外键访问到author这个表中的name值。

执行完上述代码之后就在book中创建了一个新的属性author_name,但是只在内存中,不会映射到数据库中去。

4.order_by:

指定将查询的结果根据某个字段进行排序。如果要倒叙排序,那么可以在这个字段的前面加一个负号。

示例

def index2(request):
  # 1. 将book中的price属性按照从小到大进行排序
  # books = models.Book.objects.order_by('price')
  # for book in books:
  #   print("%s-%s"%(book.name,book.price))

  # 2. 将book中的price属性按照从大到小进行排序
  books = models.Book.objects.order_by('-price')
  for book in books:
    print("%s-%s"%(book.name,book.price))
  return HttpResponse('success')

修改对应注释代码哪呢个查看到效果。

需求:对价格进行排序,价格一样的就按照页数来进行排序,价格从小到大,页数从大到小。为了方便查看效果,可以先去数据库中修改数据。

def index2(request):
  # 1. 将book中的price属性按照从小到大进行排序
  # books = models.Book.objects.order_by('price')
  # for book in books:
  #   print("%s-%s"%(book.name,book.price))

  # 2. 将book中的price属性按照从大到小进行排序
  # books = models.Book.objects.order_by('-price')
  # for book in books:
  #   print("%s-%s"%(book.name,book.price))

  # 3. 对价格进行排序,价格一样的就按照页数来进行排序,价格从小到大,页数从大到小。
  books = models.Book.objects.order_by('price','-pages')
  for book in books:
    print("%s-%s-%s"%(book.name,book.price,book.pages))
  return HttpResponse('success')

注意:

books = models.Book.objects.order_by('price','-pages')不等于books = models.Book.objects.order_by('price').order_by('-pages')

如果使用多个order_by,会把前面排序的规则给打乱,只会使用最后面的一个排序方式。

order_by方法并没有改变数据库中的信息位置,只是我们将数据取出来进行了排序。

那么如果我们对数据库中的信息进行了排序,这样我们就不用每次取数据都需要进行一次排序了。应该怎样做呢?

我们只需要在模型中添加点代码就可以了。

例如:我们在Book者恶搞模型中对价格进行排序,价格一样的就按照页数来进行排序,价格从小到大,页数从大到小。

修改Book中的class Meta中的代码:

  class Meta:
    db_table = 'book_order'
    ordering = ['price','-pages']

这样就对数据库中的信息进行了排序,我们在去数据 的时候也不用使用order_by来进行排序了。但是这样需要重新makegrations和migrate一下,这里就不做演示了。

需求:根据每本图书的销量来进行排序

from django.db.models import Q,F,Count

def index2(request):

  # 1. 将book中的price属性按照从小到大进行排序
  # books = models.Book.objects.order_by('price')
  # for book in books:
  #   print("%s-%s"%(book.name,book.price))

  # 2. 将book中的price属性按照从大到小进行排序
  # books = models.Book.objects.order_by('-price')
  # for book in books:
  #   print("%s-%s"%(book.name,book.price))

  # 3. 对价格进行排序,价格一样的就按照页数来进行排序,价格从小到大,页数从大到小。
  # books = models.Book.objects.order_by('price','-pages')
  # for book in books:
  #   print("%s-%s-%s"%(book.name,book.price,book.pages))

  # 4. 根据每本图书的销量来进行排序
  results = models.Book.objects.annotate(sale_num=Count('bookorder__id')).order_by('sale_num')
  for result in results:
    print("%s-%s"%(result.name,result.sale_num))
  return HttpResponse('success')

因为Book这个模型中没有sale_num这个属性,所以我们需要使用annotate这个方法来创建一个sale_num属性,然后使用Count方法进行赋值,然后使用order_by 进行排序。就实现了这个需求。

5. values:

用来指定在提取数据出来,需要提取哪些字段。默认情况下会把表中所有的字段全部都提取出来,可以使用values来进行指定,并且使用了values方法后,提取出的QuerySet中的数据类型不是模型,而是在values方法中指定的字段和值形成的字典。

需求: 只需要提取Book中的id 和 name

示例:

def index3(request):

  # 1. 只需要提取Book中的id 和 name
  books = models.Book.objects.values('id','name')
  for book in books:
    print(book)
  return HttpResponse('success')

注意: 返回的是一个字典类型。字典的key就是属性名,value是属性值。

需求:提取Book中的name和author__name,并且字典中的key自己指定,不使用默认的。字典的key分别为bookName和authorNmae

def index3(request):

  # 1. 只需要提取Book中的id 和 name
  # books = models.Book.objects.values('id','name')
  # for book in books:
  #   print(book)

  # 需求:提取Book中的name和author__name,并且字典中的key自己指定,不使用默认的。
  # 字典的key分别为`bookName`和`authorNmae`
  books = models.Book.objects.values(bookName=F('name'),authorName=F('author__name'))
  for book in books:
    print(book)
  return HttpResponse('success')

注意:

自己取名字不能取该模型的属性名,否则会报错。

如果在value中不传递任何参数,那么会获取这个模型所有的值。返回的还是一个字典。

6:values_list:

类似于values。只不过返回的QuerySet中,存储的不是字典,而是元组。操作和values是一样的,只是返回类型不一样。

注意: 当我们使用此方法只返回一个值的时候,那么这个元祖中只有一个值,我们可以添加一个参数flat=True,将元祖去掉,从而得到一个字符窜。只有当values_list中只有一个值的时候才能使用这个方法:

示例:

books = models.Book.objects.values_list('name',flat=True)

7. all:

获取这个ORM模型的QuerySet对象。即获取所有的数据。

获取Book中所有数据

示例:

books = models.Book.objects.all()

8.select_related:

在提取某个模型的数据的同时,也提前将相关联的数据提取出来。比如提取文章数据,可以使用select_related将author信息提取出来,以后再次使用article.author的时候就不需要再次去访问数据库了。可以减少数据库查询的次数。

def index4(request):
  books = models.Book.objects.select_related('author')
  for book in books:
    print(book.author.name)
  return HttpResponse('succrss')

注意: select_related只能使用在设置了外键的模型中(即只能在一对多模型上,不能多对一,多对多等),比如我们只在Book设置了author外键和publisher外键。那么select_related里面只能传如这两个参数,而不能传入别的参数,如BookOrder,因为我们是在BookOrder中设置的外键连接到Book,并没有在Book中设置外键连接到BookOrder这个模型。

9. prefetch_related:

这个方法和select_related非常的类似,就是在访问多个表中的数据的时候,减少查询的次数。这个方法是为了解决多对一和多对多的关系的查询问题。

需求:从book中通过prefetch_related查询BookOrder中的信息。

示例代码

def index5(request):
  books = models.Book.objects.prefetch_related("bookorder_set")
  for book in books:
    print('*'*30)
    print(book.name)
    orders = book.bookorder_set.all()
    for order in orders:
      print(order.id)
  return HttpResponse('success')

prefetch_related方法也能办到select_related方法能办到的事情,只是select_related方法效率比prefetch_related方法效率高一点。所以能使用select_related方法的话就是用这个方法。但是这两种方法的执行效率都比传统的方法执行效率高。传统的方法就是先返回book对象,再通过book去查询对应的外键的相关信息。

10. defer:

在一些表中,可能存在很多的字段,但是一些字段的数据量可能是比较庞大的,而此时你又不需要,比如我们在获取文章列表的时候,文章的内容我们是不需要的,因此这时候我们就可以使用defer来过滤掉一些字段。这个字段跟values有点类似,只不过defer返回的不是字典,而是模型。

需求:过滤掉book 的name字段

def index6(request):
  # 过滤掉book的name字段
  books = models.Book.objects.defer('name')
  for book in books:
    print(book.id)

  return HttpResponse('sucdess')

注意: 我们在使用defer过滤掉name字段之后,我们还是可以访问到name属性,是因为当我们访问name属性的时候,Django又去执行了一遍sql语句查询的代码。所以在我们开发的过程中,除非我们确定不会使用到此属性,否则不要去过滤它。

defer虽然能过滤字段,但是有些字段是不能过滤的,比如id,即使你过滤了,也会提取出来。

11. only:

跟defer类似,只不过defer是过滤掉指定的字段,而only是只提取指定的字段。

需求:只提取name属性

  # 只提取name属性
  books = models.Book.objects.only('name')
  for book in books:
    print(book.id,book.name)

注意: id这个字段我们是不能操作的,像上面一样,我们没有提取id属性,但是还是给我们提取出来了。所以id属性是一定会被提取出来的。

和defer一样,就算我们没有提取某个属性出来,我们还是可以访问到的,只是会重新执行一遍sql代码而已。

12. get:

获取满足条件的数据。这个函数只能返回一条数据,并且如果给的条件有多条数据,那么这个方法会抛出MultipleObjectsReturned错误,如果给的条件没有任何数据,那么就会抛出DoesNotExit错误。所以这个方法在获取数据的只能,只能有且只有一条。

# 获取id为1的数据
book = models.Book.objects.get(id=1)

13. create:

创建一条数据,并且保存到数据库中。这个方法相当于先用指定的模型创建一个对象,然后再调用这个对象的save方法。

publusher = models.Publisher.objects.create(name='知了出版社')

14. get_or_create:

根据某个条件进行查找,如果找到了那么就返回这条数据,如果没有查找到,那么就创建一个。

result = models.Publisher.objects.get_or_create(name='知了出版社')
print(result)

会返回一个元祖

查找的对象以及是否创建了这条数据。False就是没有创建这条数据。

15. bulk_create:

和create方法类似,只是这个方法可以一次性创建多个数据。

publusher = models.Publisher.objects.bulk_create([models.Publisher(name='123出版社'),
models.Publisher(name='abc出版社'),])

16. count:

获取提取的数据的个数。如果想要知道总共有多少条数据,那么建议使用count,而不是使用len(articles)这种。因为count在底层是使用select count(*)来实现的,这种方式比使用len函数更加的高效。

count = models.Book.objects.filter(name='xxx').count()

17. first和last:

返回QuerySet中的第一条和最后一条数据。如果为空则返回none。

18. aggregate:

使用聚合函数。

19. exists:

判断某个条件的数据是否存在。如果要判断某个条件的元素是否存在,那么建议使用exists,这比使用count或者直接判断QuerySet更有效得多。

示例代码如下:

# 最高效的判断值是否存在的方法
if Article.objects.filter(name='三国演义').exists():
  print(True)
# 比上面的方法效率低一点
if Article.objects.filter(name='三国演义').count() > 0:
  print(True)
# 还要比上面的效率低
if Article.objects.filter(name='三国演义'):
  print(True)

20. distinct:

去除掉那些重复的数据。这个方法如果底层数据库用的是MySQL,那么不能传递任何的参数。

需求:提取所有销售的价格超过80元的图书,并且删掉那些重复的,那么可以使用distinct来帮我们实现,示例代码如下:

  books = models.Book.objects.filter(bookorder__price__gte=80).distinct()
  for book in books:
    print(book.name)

并且distinct只会剔除那些完全相同的数据,如果有一个字段不相同,都不会剔除的。

如果在distinct之前使用了order_by,那么因为order_by会提取order_by中指定的字段,因此再使用distinct就会根据多个字段来进行唯一化,所以就不会把那些重复的数据删掉。

示例:

orders = models.BookOrder.objects.order_by("pages").values("book_id").distinct()

21. update:

执行更新操作,在SQL底层走的也是update命令。比如要将所有图书的价格都提高10元。

book = models.Book.objects.update(price=F('price')+5)

22. delete:

删除所有满足条件的数据。删除数据的时候,要注意on_delete指定的处理方式。

例如删除作者id大于等于3的数据

result = models.Author.objects.get(id__gte=4).delete()

删除数据时一定要对你的表了如指掌,因为可能会牵连到很多其他数据。像在这个地方将这个作者删除了之后,那么这个作者对应的图书也将会被删除。

23. 切片操作:

有时候我们查找数据,有可能只需要其中的一部分。那么这时候可以使用切片操作来帮我们完成。QuerySet使用切片操作就跟列表使用切片操作是一样的。

  # 获取1,2两条数据
  books = models.Book.objects.all()[1:3]
  for book in books:
    print(book)

以上这篇浅谈Django QuerySet对象(模型.objects)的常用方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • django model object序列化实例

    提到序列化与反序列化,通常会想到 json ,xml .在J2EE的开发中,这是很常用的技术,比如一个java class与xml之间的序列化与反序列化,我们可以通过 xstream来实现,如果是与json之间的转换,我们可以通过 gson.jar或者jsonlib.jar 来实现.方法很多,也是常见的方法. 但在python 中,我们常用的是json 的序列化,python2.7 已经包含了json package,这个也是从simplejson 基础上改变而来.这个json 包主要提供了du

  • Django对models里的objects的使用详解

    首先我们先熟悉下objects的大致概念. object是模型属性---用于模型对象和数据库交互 . objects = Manager() 是管理器类型的对象 ,是Model和数据库进行查询的接口. objects : 管理器对象 是Manager类型的对象,定义在from django.db import models中 用于模型对象和数据库交互 是默认自动生成的属性,但是可以自定义管理器对象 实例: class Students(models.Model): # stuobj = mode

  • Django ValuesQuerySet转json方式

    在使用ValuesQuerySet存放查询结果时,有时需要转为json,但并不能直接使用json.dumps()直接转,而是需要经过下面一个步骤: result_set = Apple.objects.all().values() print type(result_set) data_list = result_set[:] # queryset转为list print type(data_list) output: <class 'django.db.models.query.ValuesQ

  • 浅谈Django QuerySet对象(模型.objects)的常用方法

    准备工作: 新建一个项目,在项目中新家一个app,名字自取.将app添加值settings.py中,然后配置settings连接数据库. 在app中的models中新建模型: from django.db import models # Create your models here. class Author(models.Model): """作者模型""" name = models.CharField(max_length=100) ag

  • 浅谈django 模型类使用save()方法的好处与注意事项

    如下所示: def user_degree(self): degree = self.user.update_grade() return degree def save(self, *args, **kwargs): self.degree = self.user_degree() self.p1_user = self.get_p1() self.p2_user = self.get_second() self.p3_user = self.get_third() self.first_ge

  • 浅谈django不使用restframework自定义接口与使用的区别

    django可以使用restframework快速开发接口,返回前端所需要的json数据,但是有时候利用restframework开发的接口并不能满足所有的需求,这时候就需要自己手动开发接口,也就是将需要用到的某些对象转化为需要使用的json数据,今天记录一下django自己定义接口的一种方法与思路 假设我们定义三张数据表,分别是问卷,问题,选项.一张问卷包含不同的问题,一个问题可以设置不同的选项,自定义的接口可以实现查看所有或单个问卷的标题与id,可以查看所有或单个问题的所属问卷,问题标题,问

  • 浅谈django model的get和filter方法的区别(必看篇)

    django的get和filter方法是django model常用到的,搞清楚两者的区别非常重要. 为了说明它们两者的区别定义2个models class Student(models.Model): name = models.CharField('姓名', max_length=20, default='') age = models.CharField('年龄', max_length=20, default='') class Book(models.Model): student =

  • 浅谈Django中的数据库模型类-models.py(一对一的关系)

    如下所示: # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models # Create your models here. # 一对一关系:数据库中两个表中数据的对应关系 # 一个账户对应着一个联系人,而一个联系人有一个账户 # 一对一关系是通过在两个表之间定义相同的主键来完成 class Account(models.Model): username = models

  • 浅谈Django前端后端值传递问题

    前端后端传值问题总结 前端传给后端 通过表单传值 1.通过表单get请求传值 在前端当通过get的方式传值时,表单中的标签的name值将会被当做action的地址的参数 此时,在后端可以通过get请求相应的name值拿到对应的value值 例子: html中: <form action="{% url 'backweb:select_art' %}" method="post"> {% csrf_token %} <section class=&q

  • 浅谈django中的认证与登录

    认证登录 django.contrib.auth中提供了许多方法,这里主要介绍其中的三个: 1  authenticate(**credentials)    提供了用户认证,即验证用户名以及密码是否正确 一般需要username  password两个关键字参数 如果认证信息有效,会返回一个  User  对象.authenticate()会在User 对象上设置一个属性标识那种认证后端认证了该用户,且该信息在后面的登录过程中是需要的.当我们试图登陆一个从数据库中直接取出来不经过authent

  • 浅谈Django自定义模板标签template_tags的用处

    自定义模板标签,过滤器.英文翻译是Customtemplatetagsandfilters.customfilter自定义过滤器今天不在我的记录范围之内,以后用到再看官方文档也不迟. **问题1:**customtemplatetags到底长啥样? customtemplatetags-github Manytemplatetagstakeanumberofarguments–stringsortemplatevariables–andreturnaresultafterdoingsomepro

  • 浅谈django的render函数的参数问题

    hello.html 文件代码如下: HelloWorld/templates/hello.html 文件代码: <h1>{{ hello }}</h1> HelloWorld/HelloWorld/view.py 文件代码: # -*- coding: utf-8 -*- #from django.http import HttpResponse from django.shortcuts import render def hello(request): context = {

  • 浅谈django model postgres的json字段编码问题

    django model的json字段的编码器不能有效编码诸如uuid,datetime等数据类型,当直接存储此类型的对象到json字段中为抛出编码异常,这时可以通过JSONField字段的encoder参数指定json编码器,这里直接使用django rest framework 的 JSONEncoder from django.contrib.postgres.fields import JSONField from rest_framework.utils.encoders import

随机推荐