解决方案:
打开 Django Shell 环境,导入模型类,使用 all 方法对数据进行查询
(testenv) [root@localhost mysite3]# python3 manage.py shell
>>> from bookstore.models import Book
>>> a1 = Book.objects.all()
>>> a1
, , , , ]>
>>> for book in a1:
... print(book.title, book.pub)
...
Python 清华大学出版社
Django 清华大学出版社
JQuery 机械工业出版社
Linux 机械工业出版社
HTML5 清华大学出版社
修改 Book类对象的显示内容,修改模型类中的 __str__ 方法
# file: bookstore/models.py
class Book(models.Model):
title = models.CharField("书名", max_length=50, default="", unique=True)
pub = models.CharField("出版社", max_length=50, default="")
price = models.DecimalField("定价", max_digits=7, decimal_places=2, default=0.0)
market_price = models.DecimalField("零售价", max_digits=7, decimal_places=2, default=0.0)
def __str__(self): # 重写__str__方法
return f"{self.title}, {self.pub}, {self.price}, {self.market_price}"
class Meta:
db_table = "book"
重新打开 Django Shell 环境,导入模型类,使用 all 方法对数据进行查询
(testenv) [root@localhost mysite3]# python3 manage.py shell
>>> from bookstore.models import Book
>>> a1 = Book.objects.all()
>>> a1
, , , , ]>
>>> for book in a1:
... print(book)
...
Python, 清华大学出版社, 20.00, 25.00
Django, 清华大学出版社, 70.00, 75.00
JQuery, 机械工业出版社, 90.00, 85.00
Linux, 机械工业出版社, 80.00, 65.00
HTML5, 清华大学出版社, 90.00, 105.00
打开 Django Shell 环境,导入模型类,使用 values 方法对数据进行查询
(testenv) [root@localhost mysite3]# python3 manage.py shell
>>> from bookstore.models import Book
>>> a2 = Book.objects.values("title", "pub")
>>> a2
>>> for book in a2:
... print(book["title"], book["pub"])
...
Python 清华大学出版社
Django 清华大学出版社
JQuery 机械工业出版社
Linux 机械工业出版社
HTML5 清华大学出版社
打开 Django Shell 环境,导入模型类,使用 values_list 方法对数据进行查询
(testenv) [root@localhost mysite3]# python3 manage.py shell
>>> from bookstore.models import Book
>>> a3 = Book.objects.values_list('title', 'pub')
>>> a3
>>> for book in a3:
... print(book[0], book[1])
...
Python 清华大学出版社
Django 清华大学出版社
JQuery 机械工业出版社
Linux 机械工业出版社
HTML5 清华大学出版社
打开 Django Shell 环境,导入模型类,使用 order_by 方法对数据进行查询
>>> a4 = Book.objects.order_by("price") # 默认升序排列
>>> a4
, , , , ]>
>>> for book in a4:
... print(book.title, book.price)
...
Python 20.00
Django 70.00
Linux 80.00
JQuery 90.00
HTML5 90.00
>>> a5 = Book.objects.order_by("-price") # 通过price价格降序排列
>>> for book in a5:
... print(book.title, book.price)
...
JQuery 90.00
HTML5 90.00
Linux 80.00
Django 70.00
Python 20.00
>>> a6 = Book.objects.values("title").order_by("-price") # 和其他查询方法连用
>>> a6
>>> a6.query
>>> str(a6.query) # 查询执行的 SQL 语句
'SELECT `book`.`title` FROM `book` ORDER BY `book`.`price` DESC'
需求:制作查看所有书籍页面
视图函数: all_book
url: http://127.0.0.1:8000/bookstore/all_book
编写视图函数 bookstore -> views.py
# file: bookstore/views.py
from django.shortcuts import render
from .models import Book
def all_book(request):
all_book = Book.objects.all() # 查询所有图书
return render(request, "bookstore/all_book.html", locals())
编写指定模板文件 bookstore -> templates -> bookstore -> all_book.html
图书首页
{% for book in all_book %}
{{ book.id }}
{{ book.title }}
{{ book.pub }}
{{ book.price }}
{{ book.market_price }}
更新
删除
{% endfor %}
修改主路由文件 mysite3 -> urls.py
# file: mysite3/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
###day03###
path("test_static", views.test_static),
path("music/", include("music.urls")),
path("sport/", include("sport.urls")),
path("news/", include("news.urls")),
###day04###
path("bookstore/", include("bookstore.urls")), # 添加主路由配置
]
修改子路由文件 bookstore -> urls.py
# file: bookstore/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("all_book", views.all_book),
]
启动 Django 服务,在浏览器测试 http://127.0.0.1:8000/bookstore/all_book,查看模板是否渲染成功
打开 Django Shell 环境,导入模型类,使用 filter 方法对数据进行查询
(testenv) [root@localhost mysite3]# python3 manage.py shell
>>> from bookstore.models import Book
>>> b1 = Book.objects.filter(pub="中信出版社") # 空结果集
>>> b1
>>> b2 = Book.objects.filter(pub="清华大学出版社")
>>> b2
, , ]>
>>> str(b2.query)
'SELECT `book`.`id`, `book`.`title`, `book`.`pub`, `book`.`price`, `book`.`market_price` FROM `book` WHERE `book`.`pub` = 清华大学出版社'
>>> b3 = Book.objects.filter(pub="清华大学出版社", price=70) # 多个条件是and关系
>>> b3
]>
>>> str(b3.query) # 查询底层查询SQL语句
'SELECT `book`.`id`, `book`.`title`, `book`.`pub`, `book`.`price`, `book`.`market_price` FROM `book` WHERE (`book`.`price` = 70 AND `book`.`pub` = 清华大学出版社)'
打开 Django Shell 环境,导入模型类,使用 exclude 方法对数据进行查询
>>> from bookstore.models import Book
>>> books = Book.objects.exclude(pub="清华大学出版社", price=70)
>>> for book in books:
... print(book)
...
Python, 清华大学出版社, 20.00, 25.00
JQuery, 机械工业出版社, 90.00, 85.00
Linux, 机械工业出版社, 80.00, 65.00
HTML5, 清华大学出版社, 90.00, 105.00
get(条件)
用法:自定义模型类.objects.get(条件)
作用:返回满足条件的唯一一条数据
说明:该方法只能返回一条数据
__exact | 等值匹配 |
---|---|
__contains | 包含某个值 |
__startswith | 以 XXX 开始 |
__endswith | 以 XXX 结束 |
__gt | 大于某个值 |
__gte | 大于等于某个值 |
__lt | 小于某个值 |
__lte | 小于等于某个值 |
__in | 查找数据是否在指定范围内 |
打开 Django Shell 环境,导入模型类,使用 get 方法对数据进行查询
>>> from bookstore.models import Book
>>> b1 = Book.objects.get(title="Django") # 拿到单条数据
>>> b1
>>> b2 = Book.objects.get(title="Django123") # 数据不存在报错
bookstore.models.Book.DoesNotExist: Book matching query does not exist.
>>> books = Book.objects.get(pub="清华大学出版社") # 返回多条数据报错
bookstore.models.Book.MultipleObjectsReturned: get() returned more than one Book -- it returned 3!
如何做非等值查询,即 where id > 1,尝试:Book.objects.filter(id>1) ?结果报错
>>> from bookstore.models import Book
>>> Book.objects.filter(id>1) # 报错
Traceback (most recent call last):
File "", line 1, in
TypeError: '>' not supported between instances of 'builtin_function_or_method' and 'int'
打开 Django Shell 环境,导入模型类,使用常用的查询谓词对数据进行查询
>>> from bookstore.models import Book
>>> b1 = Book.objects.filter(id__exact=1) # __exact
]>
>>> b2 = Book.objects.filter(title__contains='o') # __contains
>>> b2
, ]>
>>> str(b2.query)
'SELECT `book`.`id`, `book`.`title`, `book`.`pub`, `book`.`price`, `book`.`market_price` FROM `book` WHERE `book`.`title` LIKE BINARY %o%'
>>> b3 = Book.objects.filter(title__startswith="D") # __startswith
>>> b3
]>
>>> str(b3.query)
'SELECT `book`.`id`, `book`.`title`, `book`.`pub`, `book`.`price`, `book`.`market_price` FROM `book` WHERE `book`.`title` LIKE BINARY D%'
>>> b4 = Book.objects.filter(price__gte=75) # __gte
>>> b4
, , ]>
>>> str(b4.query)
'SELECT `book`.`id`, `book`.`title`, `book`.`pub`, `book`.`price`, `book`.`market_price` FROM `book` WHERE `book`.`price` >= 75'
>>> b5 = Book.objects.filter(title__in=["Python", "Ansible", "Django"]) # __in
>>> b5
, ]>
>>> str(b5.query)
'SELECT `book`.`id`, `book`.`title`, `book`.`pub`, `book`.`price`, `book`.`market_price` FROM `book` WHERE `book`.`title` IN (Python, Ansible, Django)'
修改单个实体某些字段的步骤
查
- 通过 get() 得到要修改的实体对象
改
- 通过 对象.属性 的方式修改数据
保存
- 通过对象.save()保存数据
直接调用 QuerySet 的 update(属性=值) 实现批量修改
(testenv) [root@localhost mysite3]# python3 manage.py shell
>>> from bookstore.models import Book
>>> b1 = Book.objects.get(id=1)
>>> b1
>>> b1.price = 22
>>> b1.save() # 单值修改
>>> books = Book.objects.filter(pub="清华大学出版社")
>>> books
, , ]>
>>> books.update(price=1) # 批量修改
3
>>> books = Book.objects.filter(pub="清华大学出版社")
>>> for book in books:
... print(book.price)
...
1.00
1.00
1.00
需求:
解决方案:
修改指定模板文件 bookstore -> templates -> bookstore -> all_book.html
图书首页
{% for book in all_book %}
{{ book.id }}
{{ book.title }}
{{ book.pub }}
{{ book.price }}
{{ book.market_price }}
更新
删除
{% endfor %}
编写视图函数 bookstore -> views.py
from django.shortcuts import render
from django.http.response import HttpResponse, HttpResponseRedirect
from .models import Book
def all_book(request):
all_book = Book.objects.all()
return render(request, "bookstore/all_book.html", locals())
def update_book(request, book_id):
# bookstore/update_book/1
try:
book = Book.objects.get(id=book_id)
except Exception as e:
print('--update book error is:', e)
return HttpResponse('--The book is not existed')
if request.method == 'GET':
return render(request, 'bookstore/update_book.html', locals())
elif request.method == 'POST':
price = request.POST['price']
market_price = request.POST['market_price']
# 改
book.price = price
book.market_price = market_price
# 保存
book.save()
return HttpResponseRedirect('/bookstore/all_book')
编写指定模板文件 bookstore -> templates -> bookstore -> update_book.html
更改书籍
修改子路由文件 bookstore -> urls.py
# file: bookstore/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('all_book', views.all_book),
path('update_book/', views.update_book),
]
启动 Django 服务,在浏览器测试 http://127.0.0.1:8000/bookstore/all_book,测试更新数据功能
点击更新按钮
需求:
点击查看所有书籍页面中的删除;删除当前数据(伪删除)
视图函数:delete_book
url: http://127.0.0.1:8000/bookstore/delete?book_id=xx
注意:相关查询获取数据的地方,要过滤出活跃数据
解决方案:
在 Book 模型类中添加 is_active 字段,从而实现数据伪删除
class Book(models.Model):
title = models.CharField("书名", max_length=50, default="", unique=True)
pub = models.CharField("出版社", max_length=50, default="")
price = models.DecimalField("定价", max_digits=7, decimal_places=2, default=0.0)
market_price = models.DecimalField("零售价", max_digits=7, decimal_places=2, default=0.0)
is_active = models.BooleanField("是否活跃", default=True) # 添加字段
实现数据迁移、
(testenv) [root@localhost mysite3]# python3 manage.py makemigrations
(testenv) [root@localhost mysite3]# python3 manage.py migrate
修改指定模板文件 bookstore -> templates -> bookstore -> all_book.html
图书首页
{% for book in all_book %}
{{ book.id }}
{{ book.title }}
{{ book.pub }}
{{ book.price }}
{{ book.market_price }}
更新
删除
{% endfor %}
编写视图函数 bookstore -> views.py
from django.shortcuts import render
from django.http.response import HttpResponse, HttpResponseRedirect
from .models import Book
def all_book(request):
# all_book = Book.objects.all()
all_book = Book.objects.filter(is_active=True) # 修改查询所有图书方式
return render(request, "bookstore/all_book.html", locals())
def update_book(request, book_id):
# bookstore/update_book/1
try:
book = Book.objects.get(id=book_id, is_active=True) # 过滤活跃图书
except Exception as e:
print('--update book error is:', e)
return HttpResponse('--The book is not existed')
if request.method == 'GET':
return render(request, 'bookstore/update_book.html', locals())
elif request.method == 'POST':
price = request.POST['price']
market_price = request.POST['market_price']
# 改
book.price = price
book.market_price = market_price
# 保存
book.save()
return HttpResponseRedirect('/bookstore/all_book')
def delete_book(request):
# 通过获取查询字符串 book_id 拿到要删除的book的id
book_id = request.GET.get('book_id')
if not book_id:
return HttpResponse('---请求异常')
try:
book = Book.objects.get(id=book_id, is_active=True)
except Exception as e:
print('---delete book get error:', e)
return HttpResponse('---The book id is error')
# 将其is_active 改成False
book.is_active = False
book.save()
# 302跳转至all_book
return HttpResponseRedirect('/bookstore/all_book')
修改子路由文件 bookstore -> urls.py
# file: bookstore/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('all_book', views.all_book),
path('update_book/', views.update_book),
path('delete_book', views.delete_book),
]
启动 Django 服务,在浏览器测试 http://127.0.0.1:8000/bookstore/all_book,测试删除数据功能
查询数据库,查看 is_active 状态是否修改
Django 也支持直接用 SQL 语句的方式通信数据库
使用原生语句时小心 SQL 注入
打开 Django Shell 环境,导入模型类,测试SQL注入以及预防操作
(testenv) [root@localhost mysite3]# python3 manage.py shell
>>> from bookstore.models import Book
>>> s1 = Book.objects.raw("select * from book where id=%s;" % ("1 or 1=1"))
>>> s1 # SQL注入
>>> for item in s1:
... print(item.title)
...
Python
Django
JQuery
Linux
HTML5
>>> s2 = Book.objects.raw("select * from book where id=%s;", ["1 or 1=1"])
>>> for item in s2: # 防止SQL注入
... print(item.title)
...
Python