Py006-01-15单表操作之CRUD

单表操作之查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<1> all():                  查询所有结果

<2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象

<3> get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,
如果符合筛选条件的对象超过一个或者没有都会抛出错误。

<4> exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象

<5> order_by(*field): 对查询结果排序

<6> reverse(): 对查询结果反向排序

<8> count(): 返回数据库中匹配查询(QuerySet)的对象数量。

<9> first(): 返回第一条记录

<10> last(): 返回最后一条记录

<11> exists(): 如果QuerySet包含数据,就返回True,否则返回False

<12> values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
model的实例化对象,而是一个可迭代的字典序列
<13> values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

<14> distinct(): 从返回结果中剔除重复纪录

自行拷贝上一节代码的结构

  • all() 查询所有记录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def index(request):
# 添加表记录

# 方式一
# book_obj = Book(id=1,title='python红宝书',price=100,pub_date='2012-12-12',publish='人民出版社')
# book_obj.save()


# 方式二
# book_obj2 = Book.objects.create(title='php',price=100,pub_date='2012-12-12',publish='人民出版社')
# print(book_obj2.title)
# print(book_obj2.publish)
# return HttpResponse('hello')

# 查询表记录

book_list = Book.objects.all()
print(book_list)

return HttpResponse('ok')


# ---------------------------------------------------------
# 访问localhost:8000/index/
# pycharm里打印了这个
# <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]>

为什么打印的是个对象呢?

因为我们没有定义str方法

1
2
3
4
5
6
7
8
9
10
11
12
在模型models.py里添加 str方法
def __str__(self):
return self.title


# 访问localhost:8000/index/
# pycharm里打印了这个
# <QuerySet [<Book: python红宝书>, <Book: php>]>
----------------------------------------------------
# QuerySet是啥?
类似一个列表放着一个个对象,也就是一行数据
[obj1,obj2,obj3]
  • 使用for循环来处理queryset
1
2
3
4
5
6
7
8
9
10
11
def index(request):
...
# 查询表记录

book_list = Book.objects.all()
print(book_list)

for item in book_list:
print(item.title,item.price,item.publish)

return HttpResponse('ok')
  • 取数据里第一个first,最后一个last

调用者queryset对象 返回值model对象

1
2
3
4
book = Book.objects.all().first()
book2 = Book.objects.all()[0]

book3 = Book.objects.all().last()
  • 过滤filter() 返回值:queryset对象
1
2
3
4
5
6
book_list = Book.objects.filter(price=100) # [obj1,obj2]

book = Book.objects.filter(price=100).first() # 取第一条记录

# -----------------支持多个条件
Book.objects.filter(price=100,title='php')
  • get() 只有——有且一个的情况下才有意义 返回值: model对象
1
2
3
4
5
book = Book.objects.get(price=100) # 两本书都一个价 报错

book2 = Book.objects.get(price=300) # 没有300元的书 报错

book3 = Book.objects.get(title='python红宝书')
  • exclude() 跟filter 相反,排除条件的结果,返回值 queryset
1
2
3
book1 = Book.objects.filter(title='php') # title='php' 的书

book1 = Book.objects.exclude(title='php') # title!='php' 的书
  • order_by() 排序 调用者:queryset 返回值:queryset
1
2
3
4
5
res = Book.objects.all().order_by("id") # 生序
res = Book.objects.all().order_by("-id") # 降序

# 按多列规则排序 如价格相同时 按书名排序
res = Book.objects.all().order_by("price",'title')
  • count() 计数 调用者:queryset 返回值:int类型

注意:count之后不能调用别的了因为返回值不是queryset了

1
res = Book.objects.all().count()
  • exist() 这张表里有没有记录
1
2
3
4
5
6
7
8
9
10
第一种方式  
res = Book.objects.all()
if res:
print('有记录')
假如表里10万条记录,是不是很浪费

第二种
res = Book.objects.all().exist()
if res:
print('有记录')

重要方法

  • values() 调用者:queryset 返回值:queryset

需求想查询所有书籍的名称

1
2
3
4
# 很麻烦要自己for循环处理
res = Book.objects.all()
for i in res:
print(i.title)

解决方案——values() 单独取某个字段

1
2
3
4
5
6
7
8
9
10
11
12
13
res = Book.objects.all().values("price")

# <QuerySet [{'price': Decimal('100.00')}, {'price': Decimal('100.00')}]>

'''
原理
temp = []
for i in Book.objects.all():
temp.append({
"price":obj.price
})
return temp
'''

其实也可以这样使用

1
2
3
Book.objects.values("price")

实际上是这个:Book.objects.all().values("price")

也可以获取多个字段

1
Book.objects.all().values("price","title")
  • values_list() 调用者:queryset 返回值:queryset

1
2
3
4
5
6
7
8
9
10
11
12
跟 values调用方式一样
不同的是它们的返回内容

res = Book.objects.all().values_list("price")
# values_list 返回的内容是元祖形式
# <QuerySet [(Decimal('100.00'),), (Decimal('100.00'))]>



res = Book.objects.all().values("price")
# values 返回的内容是字典形式
# <QuerySet [{'price': Decimal('100.00')}, {'price': Decimal('100.00')}]>
  • distinct() 去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
table aa
----------------------
id name age
1 alex 12
2 alex 34

select distinct name from aa
-----
name
alex

select distinct id from aa
----- 没有任何意义因为id肯定不重复
id
1
2

----------------------------
res = Book.objects.all().distinct() # 没有一样 queryset里是一个个的对象

正确姿势 针对字段来使用 values()

1
res = Book.objects.all().values("price").distinct()

基于双下划线的模糊查询

注意filter里这样是错的

1
Book.objects.filter(price>100)

双下划线方法

  • 大于小于
1
2
3
Book.objects.filter(price__gt=100) # 价格大于100
Book.objects.filter(price__lt=100) # 价格小于100
Book.objects.filter(price__gt=100,price__lt=200) # 价格大于100小于200
  • 以什么开头
1
Book.objects.filter(title__startswith="py") # 以py开头
  • 包含指定内容
1
2
Book.objects.filter(title__contains="python") # 包含字符 python 不忽略大小写
Book.objects.filter(title__icontains="python") # 忽略大小写
  • 指定匹配几个值
1
Book.objects.filter(price__in=[100,200,300])
  • 范围
1
2
# 范围在 100-200
Book.objects.filter(price__range=[100,200])
  • 找日期范围
1
2
3
4
5
# 发版日期在2012年的
Book.objects.filter(pub_date__year=2012)

# 发版日期在2012年6月的
Book.objects.filter(pub_date__year=2012,pub_date__year=6)

删除操作

  • delete() 调用者:queryset/model 返回值:元祖
1
2
3
4
5
6
7
# queryset调用删除
res = Book.objects.filter(price=100).delete()

print(res) # (2,{'app001.Book':2})

# model调用删除
Book.objects.filter(price=100).first().delete()

修改操作

  • update() 调用者:queryset
1
Book.objects.filter(title='php').update(title='php2')

实战练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1 查询xx出版社出版过的价格大于200的书籍

Book.objects.filter(publish='xx出版社',price__gt=200)

2 查询2017年8月出版的所有以py开头的书籍名称

Book.objects.filter(title__startswith='py',pub_date__year=2017,pub_date__month=8)

3 查询价格为50,100或者150的所有书籍名称及其出版社名称

Book.objects.filter(price__in=[50,100,150]).values('title','publist')

4 查询价格在100到200之间的所有书籍名称及其价格

Book.objects.filter(price__range=[100,200]).values('title','price')

5 查询所有xx出版社出版的书籍的价格(从高到低排序,去重)

Book.objects.filter(publish='xx出版社').values('price').distinct().order_by('-price')