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='123@163.com')
Out[5]: <Author: liu>
方法二:
In [6]: a = Author(name='gao', email='234@163.com')
In [7]: a.save()
方法三:
In [8]: a1 = Author()
In [9]: a1.name='yang'
In [10]: a1.email='345@163.com'
In [11]: a1.save()
方法四:
In [12]: Author.objects.get_or_create(name='ya',email='456@163.com')
Out[12]: (<Author: ya>, True)
In [13]: Author.objects.get_or_create(name='ya',email='456@163.com')
Out[13]: (<Author: ya>, 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]: <QuerySet [<Author: liu>, <Author: gao>, <Author: yang>, <Author: ya>]>
In [35]: Author.objects.all()[:4]
Out[35]: <QuerySet [<Author: liu>, <Author: gao>, <Author: yang>, <Author: ya>]> # 切片操作,获取4个人,不支持负索引,切片可以节约内存,不支持负索引,后面有相应解决办法,第7条
In [36]: Author.objects.get(name='liu')
Out[36]: <Author: liu> # 名称为 WeizhongTu 的一条,多条会报错
#get是用来获取一个对象的,如果需要获取满足条件的一些人,就要用到filter
In [37]: Author.objects.filter(name='liu')
Out[37]: <QuerySet [<Author: liu>]> # 等于
In [38]: Author.objects.filter(name__exact='liu')
Out[38]: <QuerySet [<Author: liu>]> # 名称为 abc 但是不区分大小写,可以找到 ABC, Abc, aBC,这些都符合条件
In [39]: Author.objects.filter(name__regex='^liu')
Out[39]: <QuerySet [<Author: liu>]> # 正则表达式查询
# filter是找出满足条件的,当然也有排除符合某条件的
In [40]: Author.objects.exclude(name__contains='y')
Out[40]: <QuerySet [<Author: liu>, <Author: gao>]> # 排除包含 "y" 的Author对象
In [44]: Author.objects.exclude(email='345@163.com').filter(name__contains='y')
Out[44]: <QuerySet [<Author: ya>]> # 找出名称含有"y", 但是排除email是'345@163.com'的
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]: <QuerySet [<Author: sansa>, <Author: sansa>]>
单个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="111@111.com"
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]: <QuerySet [<Author: lil>, <Author: ya>]>
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]: <QuerySet [<Author: gao>, <Author: lil>, <Author: ya>, <Author: yang>]>
In [28]: Author.objects.all().order_by('-name')
Out[28]: <QuerySet [<Author: yang>, <Author: ya>, <Author: lil>, <Author: gao>]>
# 在column name 前面加一个负号,可以实现倒序
8、QuerySet 支持链式查询
In [39]: Author.objects.filter(name__contains='y').filter(email="456@163.com")
Out[39]: <QuerySet [<Author: ya>]>
9、QuerySet 不支持负索引
In [56]: Author.objects.all()
Out[56]: <QuerySet [<Author: lil>, <Author: ya>, <Author: gao>, <Author: yang>]>
In [57]: Author.objects.all().reverse()
Out[57]: <QuerySet [<Author: lil>, <Author: ya>, <Author: gao>, <Author: yang>]> # 直接用reverse()并没有起作用
In [58]: Author.objects.all().order_by('name')
Out[58]: <QuerySet [<Author: gao>, <Author: lil>, <Author: ya>, <Author: yang>]> # 按照名字排序
In [59]: Author.objects.all().order_by('name').reverse()
Out[59]: <QuerySet [<Author: yang>, <Author: ya>, <Author: lil>, <Author: gao>]> # 按照名字排序之后再逆序reverse()正常使用
10、QuerySet 重复问题,使用distinct() 去重
一般情况下,QuerySet 中不会出来重复问题,重复是很罕见的,但是当跨域多张表进行检索后,结果并到一起,可能会出来重复的值(遇到的问题)
网友评论