QuerySet API
模型objects:这个对象是 django.db.model.manager.Manger 的对象,这个类是一个空壳类,它上面的所有方法都是从 QuerySet 这个类中拷贝过来的。
1 >>>from django.db.models.manager import Manager 2 3 def index(request): 4 print(type(Book.objects)) 5 # objects:class Manager(BaseManager.from_queryset(QuerySet)): 6 # pass 7 return HttpResponse('index') 8 9 # >>> <class 'django.db.models.manager.Manager'>
QuerySet方法:
- get:只能匹配一条数据,返回符合条件的模型而不是QuerySet对象;
- filter :将满足条件的数据提取出来,返回一个新的 QuerySet 。
- exclude :排除满足条件的数据,返回一个新的 QuerySet 。
Book.objects.exclude(title__contains='hello')
- annotate :给 QuerySet 中的每个对象都添加一个使用查询表达式(聚合函数、 F表达式、 Q表达式、 Func表达式等)的新字段。
articles = Article.objects.annotate(author_name=F("author__name"))
- order_by :指定将查询的结果根据某个字段进行排序。如果要倒叙排序,那么可以在这个字段的前面加一个负号。
1 # 根据创建的时间正序排序 2 articles = Article.objects.order_by("create_time") 3 # 根据创建的时间倒序排序 4 articles = Article.objects.order_by("-create_time") 5 # 根据作者的名字进行排序 6 articles = Article.objects.order_by("author__name") 7 # 首先根据创建的时间进行排序,如果时间相同,则根据作者的名字进行排序 8 articles = Article.objects.order_by("create_time",'author__name')
1 # 还可根据annotate定义的字段进行排序, 如实现图书的销量进行排序;先获取每本书的bookorder_id数量再排序; 2 books = Book.objects.annotate(order_nums=Count("bookorder")).order_by("-order_nums") 3 for book in books: 4 print("%s:%s" % (book.name,book.order_nums))
1 # 多个order_by会根据作者的名字进行排序,而不是使用文章的创建时间。 2 articles = Article.objects.order_by("create_time").order_by("author__name") 3 4 #可在“Bookorder” 模型的“Meta”类中定义“ordering”的默认排序; 5 class Meta: 6 ordering = ['create_time','-price']
- values:只提取想要的字段,而不是全部内容;返回值为 QuerySet 对象,是一个字典,而不是模型;
1 def index1(requset): 2 # value()不加参数时会获取所有字段及对应的值; 3 # "author_name"为Book模型中author字段的name值;修改的名字不能跟模型原有字段冲突; 4 books = Book.objects.values("id","name",author_name=F("author__name")) 5 # >>> {'id': 1, 'name': '三国演义', 'author_name': '罗贯中'}... 6 7 # 使用聚合函数形成一个新的字段;如图书的销售数量order_nums; 8 books = Book.objects.values("id","name",order_nums=Count("bookorder")) 9 for book in books: 10 print(book) 11 # >>> {'id': 1, 'name': '三国演义', 'order_nums': 3}... 12 return HttpResponse('index1')
- value_list:与values类似,但装的不是字典,而是元组;
1 def index1(requset): 2 books = Book.objects.values_list("id","name") 3 # >>> (1, '三国演义')... 4 5 # flat=True:只有一个字段时可用;提取元组中的字段 6 books = Book.objects.values_list("name",flat=True) 7 for book in books: 8 print(book) 9 # >>> 三国演义... 10 return HttpResponse('index1')
- defer、only:都返回一个QuerySet对象,且都是模型而不是字典:
- defer:告诉ORM模型查询时过滤某些字段,过滤的字段再次使用时会重新发起请求;
- only:查询数据时值提取某些字段,没加在only查询的字段使用时也会查询发起请求;
- select_related:查找某个表的数据时,可一次性把相关联的数据提取出来,为以后访问数据时,不用再次查找数据库,产生一个SQL查询语句,减少开支;只能用在外键的关联对象,用于一对一或一对多。
1 def index(request): 2 # books = Book.objects.all() 3 books = Book.objects.select_related("author") 4 for book in books: 5 print(book.author.name) 6 return HttpResponse("index")
- prefetch_related:用于多对一或者多对多,产生两个SQL查询语句;注意:使用时后面不能加filter等方法,会导致产生新的SQL语句;如需查询多个条件时需导入Prefetch模块;
1 def index(requset): 2 # 查找每本书籍及其销售的id; 3 # 后加方法会使prefetch_related方法失效; 4 # books = Book.objects.prefetch_related("bookorder_set") 5 # for book in books: 6 # print(book.name) 7 # orders = book.bookorder_set.all() 8 # for order in orders: 9 # print(order.id) 10 11 # 需导入“from django.db.models import Prefetch”来使用“Prefetch”模块对其集合进行查找; 12 # 查找销售的书籍名及价格在90以上; 13 prefetch = Prefetch("bookorder_set",queryset=Bookorder.objects.filter(price__gte=90)) 14 books = Book.objects.prefetch_related(prefetch) 15 for book in books: 16 print(book.name) 17 orders = book.bookorder_set.all() 18 for order in orders: 19 print(order.id) 20 return HttpResponse('index')
- create:创建一个数据并将数据保存到数据库中;
1 def index(request): 2 # 等价代码 3 # publisher = Publisher(name="出版社3") 4 # book.save() 5 publisher = Publisher.objects.create("出版社3") 6 return HttpResponse("index")
- get_or_create:如果给定的条件有数据,则提取该数据;如果没有,会先创建数据再提取出来;
1 def index(requset): 2 publisher = Publisher.objects.get_or_create(name="出版社4") 3 return HttpResponse('index')
- bulk_create:一次性创建多条数据;
1 def index(requset): 2 publisher = Publisher.objects.bulk_create([ 3 publisher(name="出版社5"), 4 publisher(name="出版社6"), 5 ]) 6 return HttpResponse('index')
- count:获取数据的个数;
- first、last:返回QuerySet的第一条或最后一条数据;
- exists:判断某个条件的数据是否存在;
1 if Book.objects.filter(name="三国演义").exists() 2 print(True)
- distinct:去除掉重复的数据,如果底层数据库用的是MySQL,则不能传递参数
1 books = Book.objects.filter(bookorder__price__gte=80).distinct() 2 for book in books: 3 print(book) 4 5 # 使用order_by会使distinct根据多个字段进行唯一化,所以不会删除重复数据; 6 # books = Book.objects.filter(bookorder__price__gte=80).order_by("bookorder__price").distinct()
- update:一次性更新所有数据;
1 books = Book.objects.update(price=F("price")+5) 2 # books = Book.objects.all() 3 # for book in books: 4 # book.price = book.price + 5 5 # book.save()
- delete:一次性把所有满足条件的数据删除,需注意on_delete指定的处理方式;
切片操作: books = Book.objects.all()[0:2] # Book.objects.get_queryset()[0:1]
- Django将QuerySet装换为SQL语句的5种情况:
- 迭代:遍历QuerySet对象时,会先执行SQL语句,再把结果返回进行迭代。 for book in books: # books = Books.objects.all() ;
- 使用步长做切片操作:QuerySet可像列表一样做切片操作。切片操作不会执行SQL语句,需提供步长。后不能再执行filter方法;
- 调用len函数:获取QuerySet总共获取多少条数据也会执行SQL语句;
- 调用list函数:将一个QuerySet对象转换为list对象会执行SQL语句;
- 判断:对某个QuerySet进行判断,也会执行SQL语句。