21.QuerySetAPI
? QuerySet API:我们通常做查询操作的时候,都是通过模型名字.objects的方式进行操作。其实模型名字.objects是一个django.db.models.manager.Manager对象,而Manager这个类是一个“空壳”的类,他本身是没有任何的属性和方法的。他的方法全部都是通过Python动态添加的方式,从QuerySet类中拷贝过来的。 模型.objects:这个对象是 class_name = "BaseManagerFromQuerySet" class_dict = { ‘_queryset_class‘: QuerySet } class_dict.update(cls._get_queryset_methods(QuerySet)) # type动态的时候创建类 # 第一个参数是用来指定创建的类的名字。创建的类名是:BaseManagerFromQuerySet # 第二个参数是用来指定这个类的父类。 # 第三个参数是用来指定这个类的一些属性和方法 return type(class_name,(cls,),class_dict) _get_queryset_methods:这个方法就是将QuerySet中的一些方法拷贝出来 filter将满足条件的数据提取出来,返回一个新的QuerySet。具体的filter可以提供什么条件查询 exclude排除满足条件的数据,返回一个新的QuerySet。示例代码如下: Article.objects.exclude(title__contains=‘hello‘)
annotate给QuerySet中的每个对象都添加一个使用查询表达式(聚合函数、F表达式、Q表达式、Func表达式等)的新字段。示例代码如下: articles = Article.objects.annotate(author_name=F("author__name"))
aggregate使用聚合函数。 order_by:# 根据创建的时间正序排序 articles = Article.objects.order_by("create_time") # 根据创建的时间倒序排序 articles = Article.objects.order_by("-create_time") # 根据作者的名字进行排序 articles = Article.objects.order_by("author__name") # 首先根据创建的时间进行排序,如果时间相同,则根据作者的名字进行排序 articles = Article.objects.order_by("create_time",‘author__name‘) 一定要注意的一点是,多个 articles = Article.objects.order_by("create_time").order_by("author__name") 他会根据作者的名字进行排序,而不是使用文章的创建时间。 class Meta: db_table = ‘book_order‘ ordering = [‘create_time‘,‘-price‘] 还可以根据 books = Book.objects.annotate(order_nums=Count("bookorder")).order_by("-order_nums") for book in books: print(‘%s/%s‘%(book.name,book.order_nums)) values
如果我们想要提取的是这个模型上关联的对象的属性,那么也是可以的,查找顺序跟 books = Book.objects.values("id","name","author__name")
books = Book.objects.values("id",author_name=F("author__name"))
在 books = Book.objects.values("id",order_nums=Count("bookorder")) 如果调用 books = Book.objects.values() values_listd跟 books = Book.objects.values_list("id","name")
(1,"西游记") 如果给 books = Book.objects.values_list("name",flat=True)
`三国演义`
all方法查询模型下的所有数据,返回一个 select_related在查找某个表的数据的时候,可以一次性把相关联的其他表的数据都提取出来,这样可以在以后访问相关联的表的数据的时候,不用再次查找数据库,可以节省一些开销.示例代码如下: books = Book.objects.select_related("author","publisher") for book in books: print(book.author.name) # 因为在提取book的时候,使用了select_related,那么以后在访问book.author的时候,不会再次向数据库重新发起查询
prefetch_related这个方法类似与 books = Book.objects.prefetch_related("bookorder_set")
books = Book.objects.prefetch_related("bookorder_set") for book in books: print(book.name) # 这个地方如果对bookorder_set进行了操作,那么就又会产生新的sql语句,前面的prefetch_related就相当于白做了 oredrs = book.bookorder_set.fliter(price__gte=90) for order in orders: print(order.id)
# 先使用Prefetch把查找的条件写好,在放到prefetch_related中 from django.db.models import Prefetch prefetch = Prefetch("bookorder_set",queryset=Bookorder.objects.filter(price__gte=90)) books = Book.objects.prefetch_related(prefetch) for book in books: print(book.name) orders = book.bookorder_set.all() for order in orders: print(order.id) defer和only这两个方法都会返回一个 articles = list(Article.objects.defer("title")) for article in articles: # 因为在上面提取的时候过滤了title # 这个地方重新获取title,将重新向数据库中进行一次查找操作 print(article.title) for sql in connection.queries: print(‘=‘*30) print(sql) get获取满足条件的数据,返回的是具体的模型。这个函数只能返回一条数据,并且如果给的条件有多条数据,那么这个方法会抛出MultipleObjectsReturned错误,如果给的条件没有任何数据,那么就会抛出DoesNotExit错误。所以这个方法在获取数据的只能,只能有且只有一条。 create创建一条数据,并且保存到数据库中。这个方法相当于先用指定的模型创建一个对象,然后再调用这个对象的save方法。示例代码如下: article = Article(title=‘abc‘) article.save() # 下面这行代码相当于以上两行代码 article = Article.objects.create(title=‘abc‘) bulk_create一次性创建多个数据,不管多少条数据,一条SQL语句解决 get_or_create如果给定的条件有数据,那么就会把这个数据直接提取出来.如果给定的条件没有数据,那么就会先创建数据,然后再把数据返回回来. count
first和last返回QuerySet中的第一条和最后一条数据,返回值是数据的模型. exisit
if Article.objects.filter(title__contains=‘hello‘).exists(): print(True) 比使用count更高效: if Article.objects.filter(title__contains=‘hello‘).count() > 0: print(True) 也比直接判断QuerySet更高效: if Article.objects.filter(title__contains=‘hello‘): print(True) distinct
books = Book.objects.filter(bookorder__price__gte=80).distinct()
orders = BookOrder.objects.order_by("create_time").values("book_id").distinct()
update一次性可以把所有的数据都更新完 Article.objects.filter(category__isnull=True).update(category_id=3)
delete
切片操作切片操作:有时候我们查找数据,有可能只需要其中的一部分。那么这时候可以使用切片操作来帮我们完成。QuerySet使用切片操作就跟列表使用切片操作是一样的。示例代码如下: books = Book.objects.all()[1:3] for book in books: print(book)
什么时候Django会将QuerySet转换为SQL去执行:生成一个QuerySet对象并不会马上转换为SQL语句去执行。 books = Book.objects.all() print(connection.queries)
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |