《Django Web框架》
批量创建数据
Book.objects.bulk_create([obj1, obj2, obj3])
一次插入多条数据
查询数据
- 数据库的查询需要使用管理器对象进行
- 通过 MyModel.objects 管理器方法调用查询接口
方法 说明 all() 查询全部记录,返回QuerySet查询对象 get() 查询符合条件的单一记录 filter() 查询符合条件的多条记录 exclude() 查询符合条件之外的全部记录 …
-
all()方法
- 方法: all()
- 用法: MyModel.objects.all()
- 作用: 查询MyModel实体中所有的数据
- 等同于
- select * from tabel
- 等同于
- 返回值: QuerySet容器对象,是个数组,内部存放 MyModel 实例
- 示例:
from bookstore import models books = models.Book.objects.all() for book in books: print("书名", book.title, '出版社:', book.pub)
-
在模型类中定义
def __str__(self):
方法可以将自定义默认的字符串class Book(models.Model): title = ... def __str__(self): return "书名: %s, 出版社: %s, 定价: %s" % (self.title, self.pub, self.price)
-
查询返回指定列(字典表示)
-
方法: values(‘列1’, ‘列2’)
-
用法: MyModel.objects.values(…)
-
作用: 查询部分列的数据并返回
- select 列1,列2 from xxx
-
返回值: QuerySet
- 返回查询结果容器,容器内存储结构为字典,每个字典代表一条数据,
- 格式为: {‘列1’: 值1, ‘列2’: 值2}
-
示例:
from bookstore import models books = models.Book.objects.values("title", "pub") for book in books: print("书名", book["title"], '出版社:', book['pub']) print("book=", book)
-
-
查询返回指定列(元组表示)
-
方法:values_list(‘列1’,‘列2’)
-
用法:MyModel.objects.values_list(…)
-
作用:
- 返回元组形式的查询结果
-
返回值: QuerySet容器对象,内部存放
元组
- 会将查询出来的数据封装到元组中,再封装到查询集合QuerySet中
-
示例:
from bookstore import models books = models.Book.objects.values_list("title", "pub") for book in books: print("book=", book) # ('Python', '清华大学出版社')...
-
-
排序查询
-
方法:order_by
-
用法:MyModel.objects.order_by(’-列’,‘列’)
-
作用:
- 与all()方法不同,它会用SQL 语句的ORDER BY 子句对查询结果进行根据某个字段选择性的进行排序
-
说明:
-
默认是按照升序排序,降序排序则需要在列前增加’-'表示
-
示例:
from bookstore import models books = models.Book.objects.order_by("-price") for book in books: print("书名:", book.title, '定价:', book.price)
-
-
根据条件查询多条记录
-
方法: filter(条件)
-
语法:
MyModel.objects.filter(属性1=值1, 属性2=值2)
-
返回值:
- QuerySet容器对象,为列表类型,内部存放 MyModel 实例
当QuerySet没有值时: all_book=book.objects.filter(price=1111) if len(all_book)==0 print("=== not book ==== ")
QuerySet可直接通过query属性,获取当前执行的sql原生语句: pyint(all_book.query) 结果: SELECT `bookstore_book`.`id`, `bookstore_book`.`title`, `bookstore_book`.`pub`, `bookstore_book`.`price`, `bookstore_book`.`market_price` FROM `bookstore_book` WHERE `bookstore_book`.`price` = 1110
-
说明:
- 当多个属性在一起时为"与"关系,即当
Books.objects.filter(price=20, pub="清华大学出版社")
返回定价为20且
出版社为"清华大学出版社"的全部图书
- 当多个属性在一起时为"与"关系,即当
-
示例:
# 查询书中出版社为"清华大学出版社"的图书 from bookstore import models books = models.Book.objects.filter(pub="清华大学出版社") for book in books: print("书名:", book.title) 2. 查询Author实体中id为1并且isActive为True的 - authors=Author.objects.filter(id=1,isActive=True)
-
字段查找
- 字段查询是指如何指定SQL语句中 WHERE 子句的内容。
- 字段查询需要通过QuerySet的filter(), exclude() and get()的关键字参数指定。
- 非等值条件的构建,需要使用字段查询
- 示例:
# 查询作者中年龄大于30 Author.objects.filter(age__gt=30) # 对应 # SELECT .... WHERE AGE > 30;
查询谓词
- 每一个查询谓词是一个独立的查询功能
-
__exact
: 等值匹配Author.objects.filter(id__exact=1) # 等同于select * from author where id = 1
-
__contains
: 包含指定值(模糊查询like)Author.objects.filter(name__contains='w') # 等同于 select * from author where name like '%w%'
-
__startswith
: 以 XXX 开始 -
__endswith
: 以 XXX 结束 -
__gt
: 大于指定值Author.objects.filer(age__gt=50) # 等同于 select * from author where age > 50
-
__gte
: 大于等于 -
__lt
: 小于 -
__lte
: 小于等于 -
__in
: 查找数据是否在指定范围内- 示例
Author.objects.filter(country__in=['中国','日本','韩国']) # 等同于 select * from author where country in ('中国','日本','韩国')
-
__range
: 查找数据是否在指定的区间范围内# 查找年龄在某一区间内的所有作者 Author.objects.filter(age__range=(35,50)) # 等同于 SELECT ... WHERE Author BETWEEN 35 and 50;
-
详细内容参见: https://docs.djangoproject.com/en/1.11/ref/models/querysets/#field-lookups
-
示例
MyModel.objects.filter(id__gt=4) # 等同于 SELECT ... WHERE id > 4;
-
练习:
-
查询Book表中price大于等于50的信息
Book.objects.filter(price__gte=50)
-
查询Author表中姓王的人的信息
Author.objects.filter(name__startswith=‘王’)
-
查询Author表中Email中包含"wc"的人的信息
Author.objects.filter(email__contains=‘wc’)
-
- 不等的条件筛选
-
语法:
MyModel.objects.exclude(条件) -
作用:
- 返回不包含此
条件
的 全部的数据集
- 返回不包含此
-
示例:
- 查询
清华大学出版社,定价大于50
以外的全部图书
books = models.Book.objects.exclude(pub="清华大学出版社", price__gt=50) for book in books: print(book)
- 查询
-
- 查询指定的一条数据
-
语法:
MyModel.objects.get(条件) -
作用:
返回满足条件的唯一一条数据
-
返回值:
MyModel 对象[列表中的对象]
-
说明:
- 该方法只能返回一条数据
- 查询结果多余一条数据则抛出,Model.MultipleObjectsReturned异常
- 查询结果如果没有数据则抛出Model.DoesNotExist异常
-
示例:
from bookstore import models book = models.Book.objects.get(id=1) print(book.title)
-
修改数据记录
- 修改单个实体的某些字段值的步骤:
- 查
- 通过 get() 得到要修改的实体对象
- 改
- 通过 对象.属性 的方式修改数据
- 保存
- 通过 对象.save() 保存数据
- 如:
from bookstore import models abook = models.Book.objects.get(id=10) abook.market_price = "10.5" abook.save()
- 查
- 通过 QuerySet 批量修改 对应的全部字段
- 先查询是否存在,再直接调用QuerySet的update(属性=值) 实现批量修改
- 如:
# 将 id大于3的所有图书价格定为0元 books = Book.objects.filter(id__gt=3) books.update(price=0) # 将所有书的零售价定为100元 books = Book.objects.all() books.update(market_price=100)
练习:修改图书得零售价
路由: /bookstore/mod/5
删除记录
- 删除记录是指删除数据库中的一条或多条记录
- 删除单个MyModel对象或删除一个查询结果集(QuerySet)中的全部对象都是调用 delete()方法
- 删除单个对象
- 步骤
- 查找查询结果对应的一个数据对象
- 调用这个数据对象的delete()方法实现删除
- 示例:
try: auth = Author.objects.get(id=1) auth.delete() except: print(删除失败)
- 步骤
- 删除查询结果集
- 步骤
- 查找查询结果集中满足条件的全部QuerySet查询集合对象
- 调用查询集合对象的delete()方法实现删除
- 一般在models下会多添加一个布尔字段作为伪删除,通过这个字段用以标记数据的活跃程度,若执行删除则将该字段变为flase,查询数据时,均在检查该字段,只返回该字段为ture的数据.
伪删除 sActive = models.BooleanField(default=True)
- 示例:
# 删除全部作者中,年龄大于65的全部信息 auths = Author.objects.filter(age__gt=65) auths.delete()
- 步骤
聚合查询
- 聚合查询是指对一个数据表中的一个字段的数据进行部分或全部进行统计查询,查bookstore_book数据表中的全部书的平均价格,查询所有书的总个数等,都要使用聚合查询
- 不带分组聚合
-
不带分组的聚合查询是指导将全部数据进行集中统计查询
-
聚合函数:
- 定义模块:
django.db.models
- 用法:
from django.db.models import *
- 聚合函数:
- Sum, Avg, Count, Max, Min
- 定义模块:
-
语法:
- MyModel.objects.aggregate(结果变量名=聚合函数(‘列’))
-
返回结果:
- 由 结果变量名和值组成的字典
- 格式为:
- `{“结果变量名”: 值}
-
示例:
# 得到所有书的平均价格 from bookstore import models from django.db.models import Count result = models.Book.objects.aggregate(myAvg=Avg('price')) print("平均价格是:", result['myAvg']) print("result=", result) # {"myAvg": 58.2} # 得到数据表里有多少本书 from django.db.models import Count result = models.Book.objects.aggregate(mycnt=Count('title')) print("数据记录总个数是:", result['mycnt']) print("result=", result) # {"mycnt": 10}
-
- 分组聚合
-
分组聚合是指通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。
-
语法:
- QuerySet.annotate(结果变量名=聚合函数(‘列’))
-
用法步骤:
- 通过先用查询结果MyModel.objects.values. 查找查询要分组聚合的列
- MyModel.objects.values(‘列1’, ‘列2’)
- 如:
pub_set = models.Book.objects.values('pub') print(books) # <QuerySet [{'pub': '清华大学出版社'}, {'pub': '清华大学出版社'}, {'pub_hou {'pub': '机械工业出版社'}, {'pub': '清华大学出版社'}]>
- 通过返回结果的 QuerySet.annotate 方法分组聚合得到分组结果
- QuerySet.annotate(名=聚合函数(‘列’))
- 返回 QuerySet 结果集,内部存储结果的字典
- 如:
pub_count_set = pub_set.annotate(myCount=Count('pub')) print(pub_count_set) # <QuerySet [{'pub': '清华大学出版社', 'myCount': 7}, {'pub': '机械工业出版社', 'myCount': 3}]>
- .values(‘查询列名’)
- 通过先用查询结果MyModel.objects.values. 查找查询要分组聚合的列
-
示例:
- 得到哪儿个出版社共出版多少本书
def test_annotate(request): from django.db.models import Count from . import models # 得到所有出版社的查询集合QuerySet pub_set = models.Book.objects.values('pub') # 根据出版社查询分组,出版社和Count的分组聚合查询集合 pub_count_set = pub_set.annotate(myCount=Count('pub')) # 返回查询集合 for item in pub_count_set: print("出版社:", item['pub'], "图书有:", item['myCount']) return HttpResponse('请查看服务器端控制台获取结果')
-
F对象
- 一个F对象代表数据库中某条记录的字段的信息
-
作用:
- 通常是对数据库中的字段值在不获取的情况下进行操作
- 用于类属性(字段)之间的比较。
-
用法
- F对象在数据包 django.db.models 中,使用时需要先导入
from django.db.models import F
- F对象在数据包 django.db.models 中,使用时需要先导入
-
语法:
from django.db.models import F F('列名')
-
说明:
- 一个 F() 对象代表了一个model的字段的值
- F对象通常是对数据库中的字段值在不加载到内存中的情况下直接在数据库服务器端进行操作
-
示例1
- 更新Book实例中所有的零售价涨10元
models.Book.objects.all().update(market_price=F('market_price')+10) # 以下做法好于如下代码 books = models.Book.objects.all() for book in books: book.update(market_price=book.marget_price+10) book.save()
-
示例2
- 对数据库中两个字段的值进行比较,列出哪儿些书的零售价高于定价?
from django.db.models import F from bookstore import models books = models.Book.objects.filter(market_price__gt=F('price')) for book in books: print(book.title, '定价:', book.price, '现价:', book.market_price)
Q对象 - Q()
-
当在获取查询结果集 使用复杂的逻辑或
|
、 逻辑非~
等操作时可以借助于 Q对象进行操作 -
如: 想找出定价低于20元 或 清华大学出版社的全部书,可以写成
models.Book.objects.filter(Q(price__lt=20)|Q(pub="清华大学出版社"))
-
Q对象在 数据包 django.db.models 中。需要先导入再使用
from django.db.models import Q
-
作用
- 在条件中用来实现除 and(&) 以外的 or(|) 或 not(~) 操作
-
运算符:
- & 与操作
- | 或操作
- 〜 非操作
-
语法
from django.db.models import Q Q(条件1)|Q(条件2) # 条件1成立或条件2成立 Q(条件1)&Q(条件2) # 条件1和条件2同时成立 Q(条件1)&~Q(条件2) # 条件1成立且条件2不成立 ...
-
示例
from django.db.models import Q # 查找清华大学出版社的书或价格低于50的书 models.Book.objects.filter(Q(market_price__lt=50) | Q(pub_house='清华大学出版社')) # 查找不是机械工业出版社的书且价格低于50的书 models.Book.objects.filter(Q(market_price__lt=50) & ~Q(pub_house='机械工业出版社'))
原生的数据库操作方法
- 使用MyModel.objects.raw()进行 数据库查询操作查询
- 在django中,可以使用模型管理器的raw方法来执行select语句进行数据查询
注意:books = models.Book.objects.raw('select * from bookstore_book where id=%s')%(id)
使用原生语句进行数据库增删改查操作时,不能格式化语句,可能会产生sql注入.
-
语法:
MyModel.objects.raw(sql语句)
-
用法
MyModel.objects.raw('sql语句')
-
返回值:
- QuerySet 集合对象
-
示例
books = models.Book.objects.raw('select * from bookstore_book') for book in books: print(book)
- 在django中,可以使用模型管理器的raw方法来执行select语句进行数据查询
- 使用django中的游标cursor对数据库进行 增删改操作
-
在Django中可以使用 如UPDATE,DELETE等SQL语句对数据库进行操作。
-
在Django中使用上述非查询语句必须使用游标进行操作
-
使用步骤:
- 导入cursor所在的包
- Django中的游标cursor定义在 django.db.connection包中,使用前需要先导入
- 如:
from django.db import connection
- 用创建cursor类的构造函数创建cursor对象,再使用cursor对象,为保证在出现异常时能释放cursor资源,通常使用with语句进行创建操作: cur.execute(‘执行增删改SQL语句’)
- 如:
from django.db import connection with connection.cursor() as cur: cur.execute('执行SQL语句')
- 如:
- 示例
# 用SQL语句将id 为 10的 书的出版社改为 "XXX出版社" from django.db import connection with connection.cursor() as cur: cur.execute('update bookstore_book set pub_house="XXX出版社" where id=10;') with connection.cursor() as cur: # 删除 id为1的一条记录 cur.execute('delete from bookstore_book where id=10;')
- 导入cursor所在的包
-
SELECT bookstore_book
.id
, bookstore_book
.title
, bookstore_book
.pub
, bookstore_book
.price
, bookstore_book
.market_price
FROM bookstore_book
WHERE bookstore_book
.price
= 1110
SELECT bookstore_book
.id
, bookstore_book
.title
, bookstore_book
.pub
, bookstore_book
.price
, bookstore_book
.market_price
FROM bookstore_book
WHERE (bookstore_book
.price
= 1110 AND bookstore_book
.title
= abc)
<QueryDict: {‘title’: [‘人生啊’], ‘pub’: [‘中信’], ‘price’: [’’], ‘market_price’: [’’]}>