继续数据的查询
filter(属性名1=值1,属性名2=值2)
语法:Mymodel.objects.filter(…)
作用:指定关键字的值来查询数据,返回的是一个QuerySet,存放的object实例
括号中可以传递多个查询参数,用逗号隔开,相当于 “与” 的操作。
这里对Book类中的__str__函数进行了定义,这样显示的更加清楚
def __str__(self):
return "书名为:{},出版社为:{},价格为:{},单价为:{}".format(self.title, self.pub, self.price, self.mark_price)
In [1]: from bookstore.models import Book
In [2]: b1 = Book.objects.filter(title='Python')
In [3]: b1
Out[3]: <QuerySet [<Book: 书名为:Python,出版社为:清华大学出版社,价格为:20.00,单价为:25.00>]>
In [8]: Book.objects.filter(pub='清华大学出版社')
Out[8]: <QuerySet [<Book: 书名为:Python,出版社为:清华大学出版社,价格为:20.00,单价为:25.00>, <Book: 书名为:Django,出版社为:清华大学出版社,价格为:70.00,单价为:75.00>, <Book:
书名为:HTML5,出版社为:清华大学出版社,价格为:90.00,单价为:105.00>]>
In [9]: Book.objects.filter(pub='清华大学出版社',title='Django')
Out[9]: <QuerySet [<Book: 书名为:Django,出版社为:清华大学出版社,价格为:70.00,单价为:75.00>]>
In [11]: b1 = Book.objects.filter(pub='清华大学出版社',title='Django')
In [12]: print(b1.query)# 这个方法可以显示在Mysql中对该数据进行查询的代码段
SELECT `book`.`id`, `book`.`title`, `book`.`pub`, `book`.`price`, `book`.`mark_price` FROM `book` WHERE (`book`.`pub` = 清华大学出版社 AND `book`.`title` = Django)
exclude(条件)
语法:MyModel.objects.exclude(条件)
作用:返回除这个条件以外的所有数据
返回值:QuerySet对象,内容为Model对象
In [16]: Book.objects.exclude(pub='清华大学出版社',price=20.00)# 除了清华大学出版社,且价格为20.00的数据,其他所有的都输出
Out[16]: <QuerySet [<Book: 书名为:Java,出版社为:电子科技大学出版社,价格为:25.00,单价为:30.00>, <Book: 书名为:Django,出版社为:清华大学出版社,价格为:70.00,单价为:75.00>, <Boo
k: 书名为:JQure,出版社为:机械工业出版社,价格为:90.00,单价为:85.00>, <Book: 书名为:Linux,出版社为:机械工业出版社,价格为:80.00,单价为:65.00>, <Book: 书名为:HTML5,出版社为:
清华大学出版社,价格为:90.00,单价为:105.00>]>
get(条件)
语法:MyModel.objects.get(条件)
作用:返回一条数据,有且仅有一条,如果查询多与一天,或者不含有该条件的数据,就会抛出异常
返回值:model对象
In [18]: Book.objects.get(title='Python')
Out[18]: <Book: 书名为:Python,出版社为:清华大学出版社,价格为:20.00,单价为:25.00>
查询谓词
做灵活的查询操作的时候需要用到查询谓词,比如大小于等
每一个查询谓词都是一个独立的查询功能
__exact:等值匹配
Book.objects.filter(id__exact=1) # 表示查询id值为1的数据
__contains:包含匹配
Book.objects.filter(title__contain=‘a’)# 查询title中含有’a’的数据
__startswith: 以xxx开始
__endswith: 以xxx结束Book.object.filter(title__startswith=‘py’)# 查询以py开头的title数据
Book.object.filter(title__startswith=‘on’)# 查询以on结尾的title数据
__gt:大于
__gte:大于等于
__lt:小于
__lte:小于等于Book.objects.filter(id_gt=1) # 返回id大于1的数据
Book.objects.filter(id_gte=1) # 返回id大于等于1的数据
Book.objects.filter(id_lt=1) # 返回id小于1的数据
Book.objects.filter(id_lte=1) # 返回id小于等于1的数据
__in:查询是否在一个列表中
__range:在指定范围的数据Book.objects.filter(title_in=[‘Python’,‘Java’]) # 查询在这个列表中的数据
Book.objects.filter(id_range=(1,5)) # 查询在1到5之间的数据
更多查询谓词https://docs.djangoproject.com/en/2.2/ref/models/querysets/#field-lookups
更新操作
更新单个数据
- 查询—get()方法
- 修改—对象.属性=值
- 保存—对象.save()
In [21]: b1 = Book.objects.get(title='Python')
In [22]: b1.price = 1000
In [23]: b1.save()
In [24]: b1
Out[24]: <Book: 书名为:Python,出版社为:清华大学出版社,价格为:1000,单价为:25.00>
批量更新数据
- 先返回一个QuerySet值
- 直接调用QuerySet的update(属性=值)的操作
book1 = Book.objects.filter(id__gt=1)
book1.update(price=0)
完善bookstore/all_book/这个网页中的更新的操作
要求:
点击更新跳转到一个新的页面,对该行数据进行更改
只允许更改price
和marker_price
的值
- 首先要思考没一行中更新的url如何设置,可以添加筛选器的方式
<a href="/bookstore/update/{{ book.id }}">更新</a>
-
创建一个更新的主路由update
path('update/<int:book_id>',views.update)
-
在views中实现函数
def update(requests, book_id):
try:# 根据id获取book对象
book = Book.objects.get(id=book_id)
except Exception as e:
print('--update book error is %s' % e)
return HttpResponse('ERROR')
if requests.method == "GET":# 请求为GET时,返回一个新的修改页面,即为点击更新时
return render(requests, 'update.html', locals())
elif requests.method == "POST":# 请求为POST时,对数据库中的数据进行更新,返回主页面,即为点击提交时
price = requests.POST['price']
market_price = requests.POST['market_price']
book.price = price
book.market_price = market_price
book.save()
print(1)
return HttpResponseRedirect('/bookstore/all_book')
- 在templates中创建更新的界面模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/bookstore/update/{{ book.id }}" method="POST">
<!-- 创建一个表单属性,向/bookstore/update/{{ book.id }}发送数据,类型为POST型-->
<p>
title<input type="text" disabled="disabled" name="title" value="{{ book.title }}">
<!-- title为不可更改的属性,设置disabled为disabled-->
</p>
<p>
pub<input type="text" disabled="disabled" name="pub" value="{{ book.pub }}">
</p>
<p>
price<input type="number" name="price" value="{{ book.price }}" max="200">
<!-- price为可更改的属性,但是有取值范围,所以设置其值要在200以内-->
</p>
<p>
market_price<input type="number" name="market_price" value="{{ book.mark_price }}" max="200">
</p>
<p>
<input type="submit" value="提交">
<!-- 最后添加一个提交按钮-->
</p>
</form>
</body>
</html>
- 然后就可以点击更新进行数据的更新了
数据的删除
单个数据的删除
首先要获取到QuerySet对象
然后执行对象.delete()的方法就可以删除了
In [1]: from bookstore.models import Book
In [2]: b1 = Book.objects.get(id=2)
In [3]: b1
Out[3]: <Book: 书名为:Java,出版社为:电子科技大学出版社,价格为:25.00,单价为:30.00>
In [4]: b1.delete()
Out[4]: (1, {'bookstore.Book': 1})
伪删除
不会把数据库中的对象真的删除,在表中添加一个新的bool属性
is_active
(默认为True),执行伪删除时,将is_active
字段设置为False,就可以了
注意:使用伪删除的时候,确保显示数据的地方均加了`is_active=True`的过滤查询
完善删除操作
- 在Book类中添加一个BooleanField()属性,默认为True,并更新到数据库中
- 在views中创建一个新的函数
def delete(requests):
book_id = requests.GET['book_id']
try:
book = Book.objects.get(id=book_id)
except Exception as e:
print('Delete error is %s ' % e)
return HttpResponse("ERROR")
if requests.method == "GET":
book.is_active = False
book.save()# 修改了数据,就一定要保存一下
return HttpResponseRedirect('/bookstore/all_book')# 返回主页面
- 创建一个新路由
path('delete',views.delete)
- 修改主页面的html文件,将删除的a标签的href加上
<a href="/bookstore/delete?book_id={{ book.id }}">删除</a>
然后就可以进行删除数据了
django中的F对象
一个F对象表述数据库中某条记录 字段信息
语法:from django.db.models import F
F(‘列’)作用:
通常是在数据库的值在不获取的情况下进行操作
用于类属性(字段)之间的比较例:
Book.objects.update(price=F(‘price’)+1)
这个代码是将说有书籍的price在原来的基础上加一,这个可以处理高并发的事件,
注意和for i in Book.object.all() :
i.price = i.price+1
i.save()的比较,F是不用得到原来的数据,只是自增的一个操作,而下面的是还要取得原来的数据再将其进行加和操作
In [6]: Book.objects.all()
Out[6]: <QuerySet [<Book: 书名为:Python,出版社为:清华大学出版社,价格为:150.00,单价为:200.00>, <Book: 书名为:Django,出版社为:清华大学出版社,价格为:70.00,单价为:75.00>, <Book
: 书名为:JQure,出版社为:机械工业出版社,价格为:90.00,单价为:85.00>, <Book: 书名为:Linux,出版社为:机械工业出版社,价格为:80.00,单价为:65.00>, <Book: 书名为:HTML5,出版社为:清
华大学出版社,价格为:90.00,单价为:105.00>]>
In [7]: Book.objects.update(price=F('price')+1)
Out[7]: 5
In [8]: Book.objects.all()
Out[8]: <QuerySet [<Book: 书名为:Python,出版社为:清华大学出版社,价格为:151.00,单价为:200.00>, <Book: 书名为:Django,出版社为:清华大学出版社,价格为:71.00,单价为:75.00>, <Book
: 书名为:JQure,出版社为:机械工业出版社,价格为:91.00,单价为:85.00>, <Book: 书名为:Linux,出版社为:机械工业出版社,价格为:81.00,单价为:65.00>, <Book: 书名为:HTML5,出版社为:清
华大学出版社,价格为:91.00,单价为:105.00>]>
Q对象
实现逻辑或|,逻辑非~
语法:from django.db.models import Q
Q(条件1)|Q(条件2) 这就是逻辑或
Q(条件1)&~Q(条件2) 逻辑与非,条件1成立且条件2不成立例
Book.objects.filter(Q(price__lt=10)|Q(title__in=[‘Python’,‘Django’]))
取价格小于10的数据,或者书名为Python或Django的数据
In [4]: Book.objects.filter(Q(price__lt=10)|Q(title__in=['Python','Django']))
Out[4]: <QuerySet [<Book: 书名为:Python,出版社为:清华大学出版社,价格为:150.00,单价为:200.00>, <Book: 书名为:Django,出版社为:清华大学出版社,价格为:70.00,单价为:75.00>]>