django QuerySet API

Django模型中偶尔我们学到了一些基本的创建也查询。这里专门来讲一下数据库接口相关的接口(QuerySet API)

从数据库中查询出来的结果一般是一个集合,这个集合叫做QuerySet文中的例子大部分是基于这个blog/models.py

from django.db import models
# Create your models here.

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.IntegerField()

    def __str__(self):
        return self.name


class Author(models.Model):
    name = models.CharField(max_length=50)
    email = models.TextField()
    
    def __str__(self):
        return self.name


class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    authors = models.ManyToManyField(Author)
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()
    
    def __str__(self):
        return self.headline
1、QuerySet 创建对象的方法
In [2]: from people.models import *

In [3]: b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')

In [4]: b.save()

总之,一共有四种方法

方法一:

In [5]: Author.objects.create(name='liu', email='[email protected]')
Out[5]: 

方法二:

In [6]: a = Author(name='gao', email='[email protected]')

In [7]: a.save()

方法三:

In [8]: a1 = Author()

In [9]: a1.name='yang'

In [10]: a1.email='[email protected]'

In [11]: a1.save()

方法四:

In [12]: Author.objects.get_or_create(name='ya',email='[email protected]')
Out[12]: (, True)

In [13]: Author.objects.get_or_create(name='ya',email='[email protected]')
Out[13]: (, False)
# 首先尝试获取,不存在就创建,可以防止重复
# 返回值(object,True/False)

备注:前三种方法返回的都是对应的object,最后一种方法返回的是一个元组,(object,True/False),创建时返回True,已存在时返回False
当有一对多、多对一、或者多对多的关系的时候,先把相关的对象查询出来

In [27]:entry = Entry.objects.get(id=1)

In [28]: cheese_blog = Blog.objects.get(name='Beatles Blog')

In [29]: entry.blog = cheese_blog

In [30]: entry.save()
2、获取对象的方法
In [34]: Author.objects.all()  # 查询所有
Out[34]: , , , ]>

In [35]: Author.objects.all()[:4]
Out[35]: , , , ]>  # 切片操作,获取4个人,不支持负索引,切片可以节约内存,不支持负索引,后面有相应解决办法,第7条

In [36]: Author.objects.get(name='liu')
Out[36]:   # 名称为 WeizhongTu 的一条,多条会报错
 
#get是用来获取一个对象的,如果需要获取满足条件的一些人,就要用到filter
In [37]: Author.objects.filter(name='liu')
Out[37]: ]>  # 等于

In [38]: Author.objects.filter(name__exact='liu')
Out[38]: ]>  # 名称为 abc 但是不区分大小写,可以找到 ABC, Abc, aBC,这些都符合条件
 
In [39]: Author.objects.filter(name__regex='^liu')
Out[39]: ]>  # 正则表达式查询
 
# filter是找出满足条件的,当然也有排除符合某条件的
In [40]: Author.objects.exclude(name__contains='y')
Out[40]: , ]>  # 排除包含 "y" 的Author对象

In [44]: Author.objects.exclude(email='[email protected]').filter(name__contains='y')
Out[44]: ]>  # 找出名称含有"y", 但是排除email是'[email protected]'的
3、删除符合条件的结果

和上面类似,得到满足条件的结果,然后delete就可以(危险操作,正式场合操作务必慎重),比如:

In [47]: Author.objects.filter(name__contains='g').delete()
Out[47]: (2, {'people.Author': 2, 'people.Entry_authors': 0})  # 删除 名称中包含“g”得人

In [48]: Author.objects.filter(name__contains='g').delete()
Out[48]: (0, {})  # 没有名称中包含”g“的人

In [49]: a = Author.objects.filter(name__contains='g')
In [50]: a.delete()
Out[50]: (0, {})  # 写成两条语句也是可以的,效果一样,但是实际上Django只执行了一条SQL语句
4、更新某个内容

批量更新,适用于all()、filter()、exclude()等后面(危险操作,正式场合操作务必慎用)

In [64]: Author.objects.filter(name__contains='l').update(name="sansa")
Out[64]: 2  # 名字中包含“l”得人都改成“sansa” 返回2,说明修改了两条数据

In [65]: Author.objects.filter(name__contains='s')
Out[65]: , ]>

单个object更新,适合于.get(),get_or_create(),update_or_create()等得到的obj,和新建很类似。

In [4]: a = Author.objects.get(name="li")

In [5]: a.name="lil"

In [6]: a.email="[email protected]"

In [7]: a.save()  # 最后不要忘记保存!!!
5、QuerySet 是可迭代的
In [20]: a = Author.objects.all()

In [21]: for e in a:
    ...:     print(e)
    ...:     
lil
ya
gao
yang

Author.objects.all() 或者 QuerySet 是查询所有的Author条目。
注意事项:
1、如果只检查Author中是否有对象,应该用

In [22]: Author.objects.all().exists()
Out[22]: True

2、QuerySet 支持切片,可以节省内存

In [23]: Author.objects.all()[:2]
Out[23]: , ]>

3、用len(a)可以得到Author的数量,但是推荐用:

In [24]: Author.objects.count()
Out[24]: 4
# 或者用的是SQL:select count(*)

4、list(a)可以强行将QuerySet变成列表

6、QuerySet是可以用pickle序列化到硬盘在读取出来的
>>> import pickle
>>> query = pickle.loads(s)     # Assuming 's' is the pickled string.
>>> qs = MyModel.objects.all()
>>> qs.query = query            # Restore the original 'query'.
7、QuerySet 查询结果排序

作者按照名称排序

In [27]: Author.objects.all().order_by('name')
Out[27]: , , , ]>

In [28]: Author.objects.all().order_by('-name')
Out[28]: , , , ]>
# 在column name 前面加一个负号,可以实现倒序
8、QuerySet 支持链式查询
In [39]: Author.objects.filter(name__contains='y').filter(email="[email protected]")
Out[39]: ]>
9、QuerySet 不支持负索引
In [56]: Author.objects.all()
Out[56]: , , , ]>

In [57]: Author.objects.all().reverse()
Out[57]: , , , ]>  # 直接用reverse()并没有起作用

In [58]: Author.objects.all().order_by('name')
Out[58]: , , , ]>  # 按照名字排序

In [59]: Author.objects.all().order_by('name').reverse()
Out[59]: , , , ]>  # 按照名字排序之后再逆序reverse()正常使用
10、QuerySet 重复问题,使用distinct() 去重

一般情况下,QuerySet 中不会出来重复问题,重复是很罕见的,但是当跨域多张表进行检索后,结果并到一起,可能会出来重复的值(遇到的问题)

你可能感兴趣的:(django QuerySet API)