目录
三、update vs save vs bulk_update
ORM (Object Relational Mapping)
含义:物件导向(面向对象)
实际理解:代码里的model对应pgadmin的tableDjango CRUD 四大事务:增 create 删 delete 改 update 查 read
一、批量更新(bulk_update)
一旦使用到queryset的update和create時,一定要注意是不是批量执行。
例子:更新书籍封面颜色coverColor
下面是models的设定
# 主表Book的model
class Book(models.Model):
authorid = models.ForeignKey(Author, related_name="authorId", on_delete=models.CASCADE, limit_choices_to={"active": True}, verbose_name=_("authorName"))
booktype = models.CharField(verbose_name=_("BookType"), max_length=40)
coverColor = models.CharField(verbose_name=_("Cover"), max_length=40)
fontColor = models.CharField(verbose_name=_("Font"), max_length=40)
# 外键表Author的model
class Author(models.Model):
name = models.CharField(verbose_name=_("authorName"), max_length=40)
age = models.IntegerField(default=0)
用法:
# 第一种:
bookqry = models.Book.objects.filter(coverColor__in=['red', 'blue'])
for c in bookqry:
c.fontColor = 'red'
c.coverColor= 'purple'
models.Book.objects.bulk_update(bookqry, ['fontColor ', 'coverColor'])
# 第二种:
booklist = ['数据结构1', '数据结构2']
book_price = {'数据结构1':['60', '清北社1'], '数据结构2':['70', '清北社2'], }
def __bulk_update_book(self, booklist, book_price, lastevent):
book_qst = models.Book.objects.filter(bookname__in=booklist)
new_list = list()
for b in book_qst:
b.price = i.price + int(book_price[i.bookname][0])
b.place = int(book_price[i.price][1])
b.lastevent = lastevent
new_list.append(b)
models.Book.objects.bulk_update(new_list, ['price ', 'place', 'lastevent'], batch_size=1000)
# 其中,batch_size作用于数据量大的情况下
二、update vs save
(一)用法
update是批量更新数据库,而save是单个执行更新。 | ||
---|---|---|
book_objs.update(fontColor='red') | 和 | book_obj.fontColor = 'red' book_obj.save() |
其中:book_objs = models.Book.objects.filter(coverColor='red')是批量的books, book_obj = models.Book.objects.filter(coverColor='red').first()是单个的book |
(二)注意
1. update:更新多笔数据
给所有book的fontColor,賦值'red'。
2. save:更新一笔数据
只更新一個book。
3. 最好传入 update_fields 参数
只控制需更新的字段(其他字段保持原状)。
例如:
book_obj.fontColor = 'red'
book_obj.save(update_fields=[" fontColor "])
原因:
针对多线程更新同个表时,若每个线程save不同的栏位值,最终,只会保留最后一个执行的多线程save的栏位值(相当于之前的线程save的值会被覆盖掉)
(三)執行效率
从SQL的执行上看,update优于save方式。
从使用上看,update适用于批量数据更新,而save只适合做单条记录的数据更新操作。
update能返回更新的记录条数,save没有返回值。
三、update vs save vs bulk_update
(一)对比
1.save 适用于单笔数据更新(前提是只能获取一笔数据,queryset可以加first,也可以不加first,但前提是记录只存在一笔)
2.update 适用于更新多笔数据,相同栏位赋予相同的值(进行相同赋值的批量更新)
3.bulk_update 适用于更新多笔数据,相同的栏位不同的值(也就是更新多个对象)
4.注意:update一定不能结合.first(),但是update可以结合.get(当只有一笔数据时)
(二)更新主表的外键栏位值
# 需要先在外键表查询,得到authorqry的Object查询集
authorqry = models.Author.objects.filter(name='萝卜干').first()
# 将外键的查询集放入到主表,作查询条件
models.Book.objects.filter(authorid=authorqry).update(
fontColor='red',
coverColor='purple',
)
(三)获取 update 前、后的数据
1. 影响
update 前的数据,会在 update 后被更新。
(即,最新数据,使用了copy.deepcopy 深拷贝也无效)
2. 怎样保持update之前的数据不会更变呢?
解决办法:结合列表生成式。
get_qst = models.book.objects.all()
deep_old_data = [i for i in get_qst] # 深拷贝 (列表生成式)
new_old_data = get_qst.update(desc='测试')
# deep_old_data 表示旧数据(不会被update操作所改变)
# new_old_data 表示更新的笔数(是int类型)
update 后的queryset数据,仅仅表示更新的笔数(int类型)。