Django数据库操作之save与update的使用


Posted in Python onApril 01, 2020

Python框架Django有着诸多优点,它提供的models可以让开发者方便地操作数据库,但正是由于对上层的良好的封装,使得提升数据库操作性能必须要清楚地知道Django的数据库操作到底执行了哪些SQL语句。

例如数据更新操作,对单条记录,可以使用save或者是update两种方式

在Django工程下的settings.py下将log设置为DEBUG,即可查看save和update分别执行了哪些SQL语句

如有一张表名叫做Example

使用save:

k = Example.objects.get(id=481)
k.total_calories = 12
k.save()

执行的SQL语句如下所示:

SELECT (1) AS `a` FROM `Example` WHERE `
Example`.`id` = 481 LIMIT 1; args=(481,)
UPDATE `Example` SET `user_id` = asdfasdf, `event_id` = -1, `join_type` = 0, `name` = , `phon
e` = , `email` = , `company_name` = , `address` = , `if_type` = 0, `code` = , `l
ocation` = , `total_days` = 0, `total_length` = 0, `total_calories` = 12, `comme
nts` = , `reserved_1` = , `reserved_2` = , `reserved_3` = , `reserved_4` = , `re
served_5` = , `create_datetime` = 2015-02-02 17:43:53 WHERE `Example`
.`id` = 481 ; args=(u'asdfasdf', -1, 0, u'', u'', u'
', u'', u'', 0, u'', u'', 0, 0, 12, u'', u'', u'', u'', u'', u'', u'2015-02-02 1
7:43:53', 481)

首先要查询k这条记录,然后save()的时候提交更新的内容,发现更新的时候把Example中的有字段都SET赋值的一次

使用update

Example.objects.filter(id=481).update(total_calories = 10)

执行的SQL语句是:

UPDATE `Example` SET `total_calories` = 1
0 WHERE (`Example`.`user_id` = asdfasdf
AND `Example`.`id` = 481 ); args=(10, u'asdfasdf', 481)

这条SQL语句简短而且执行速度要优于使用save的速度。

从SQL的执行情况来看,使用upate是要优于save方式的。

从使用情境上看,update更加适用于批量数据更新,而save则更适合当然也只适合做单条记录的数据更新操作了。

在使用Django的数据模型操作数据库时,了解这些底层的SQL操作很有必要。

补充知识:如何理解Django的save(commit=False)方法和save_m2m()方法

什么时候使用save(commit=False)方法,save_m2m方法以及如何使用是Django表单forms进阶必需了解的知识。我们今天就带你来看一看。

何时使用save(commit=False)方法

Stackoverflow上其实已经有了一段非常精炼的答案。英文原文如下,我把它翻译了一下:

That's useful when you get most of your model data from a form, but need to populate some null=False fields with non-form data. Saving with commit=False gets you a model object, then you can add your extra data and save it.

当你通过表单获取你的模型数据,但是需要给模型里null=False字段添加一些非表单的数据,该方法会非常有用。如果你指定commit=False,那么save方法不会理解将表单数据存储到数据库,而是给你返回一个当前对象。这时你可以添加表单以外的额外数据,再一起存储。

save(commit=False)方法实际应用案例

下面我们来看一个实际应用案例。我们创建了一个叫文章Article的模型,里面包含title, body和作者author等多个字段,其中author字段非空null=False。我们由Article模型创建了一个ArticleForm表单,可以让用户发表新文章,但是我们故意把author字段除外了,因为我们不希望用户编辑作者。

最后用户提交的表单数据里肯定没有author,当这样的数据提交到数据库时肯定会有问题的。所以我们先通过 article = form.save(commit=False)创建article实例,此时让Django先不要发送数据到数据库,等待我们把author添加好后,再把数据一起存储到数据库中。

下面是视图文件views.py的代码。最重要的是ArticleForm构成和article_create方法。

from .models import Article
from django.forms import ModelForm
from django.http import HttpResponseRedirect
from django.shortcuts import render

class ArticleForm(ModelForm):
 class Meta:
  model = Article
  exclude = ['author']


def article_create(request):
 if request.method == 'POST':
  form = ArticleForm(request.POST)
  if form.is_valid():
   article = form.save(commit=False)
   # commit=False告诉Django先不提交到数据库.
   article.author = request.user # 添加额外数据
   article.save() # 发送到数据库

   return HttpResponseRedirect("/blog/")
 else:
  form = ArticleForm()
 return render(request, 'blog/article_create_form.html', {'form': form})

如果你使用Django自带的基于类的视图(CBV), 你可以使用form_valid方法完成上述同样的操作。具体代码如下。

from django.views.generic.edit import CreateView
from .models import Article
from django.forms import ModelForm


# Create your views here.
class ArticleForm(ModelForm):
 class Meta:
  model = Article
  exclude = ['author']

  
class ArticleCreateView(CreateView):
 model = Article
 form_class = ArticleForm
 template_name = 'blog/article_create_form.html'

 # Associate form.instance.user with self.request.user
 def form_valid(self, form):
  form.instance.author = self.request.user
  return super().form_valid(form)

何时使用save_m2m方法及如何使用

save_m2m方法只用来存储多对多的关系。当你同时满足下面两个条件时,你需要使用此方法。如果你直接使用save()或form_valid()方法,是可以直接存储多对多(m2m)关系的,不需要用save_m2m。

你使用了save(commit=False)方法

你的model里有多对多的关系(比如tags)

假设我们文章模型里有tags这个多对多的字段,我们的article_create方法需要增加一行。

def article_create(request):
 if request.method == 'POST':
  form = ArticleForm(request.POST)
  if form.is_valid():
   article = form.save(commit=False)
   # commit=False tells Django that "Don't send this to database yet.

   article.author = request.user # Set the user object here
   article.save() # Now you can send it to DB
   form.save_m2m()

   return HttpResponseRedirect("/blog/")
 else:
  form = ArticleForm()
 return render(request, 'blog/article_create_form.html', {'form': form})

以上这篇Django数据库操作之save与update的使用就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中的map、reduce和filter浅析
Apr 26 Python
在主机商的共享服务器上部署Django站点的方法
Jul 22 Python
深入解析Python设计模式编程中建造者模式的使用
Mar 02 Python
pycharm下查看python的变量类型和变量内容的方法
Jun 26 Python
10分钟教你用Python实现微信自动回复功能
Nov 28 Python
python实现翻转棋游戏(othello)
Jul 29 Python
Python实现Restful API的例子
Aug 31 Python
基于python判断目录或者文件代码实例
Nov 29 Python
Python在终端通过pip安装好包以后在Pycharm中依然无法使用的问题(三种解决方案)
Mar 10 Python
Python devel安装失败问题解决方案
Jun 09 Python
解决Django响应JsonResponse返回json格式数据报错问题
Aug 09 Python
python爬虫之利用selenium模块自动登录CSDN
Apr 22 Python
django model通过字典更新数据实例
Apr 01 #Python
django执行原始查询sql,并返回Dict字典例子
Apr 01 #Python
python 日志 logging模块详细解析
Mar 31 #Python
django迁移文件migrations的实现
Mar 31 #Python
详解用Pytest+Allure生成漂亮的HTML图形化测试报告
Mar 31 #Python
浅谈Django中的QueryDict元素为数组的坑
Mar 31 #Python
Python + selenium + crontab实现每日定时自动打卡功能
Mar 31 #Python
You might like
国产动画《伍六七》原声大碟大卖,啊哈娱乐引领音乐赋能IP的新尝试
2020/03/08 国漫
全国FM电台频率大全 - 14 江西省
2020/03/11 无线电
header中Content-Disposition的作用与使用方法
2012/06/13 PHP
php类声明和php类使用方法示例分享
2014/03/29 PHP
JavaScript 异步调用框架 (Part 4 - 链式调用)
2009/08/04 Javascript
EasySlider 基于jQuery功能强大简单易用的滑动门插件
2010/06/11 Javascript
jQuery 获取和设置select下拉框的值实现代码
2013/11/08 Javascript
JQuery中使用.each()遍历元素学习笔记
2014/11/08 Javascript
jQuery操作cookie方法实例教程
2014/11/25 Javascript
JS自定义选项卡函数及用法实例分析
2015/09/02 Javascript
浏览器环境下JavaScript脚本加载与执行探析之动态脚本与Ajax脚本注入
2016/01/19 Javascript
js点击文本框弹出可选择的checkbox复选框
2016/02/03 Javascript
asp.net+jquery.form实现图片异步上传的方法(附jquery.form.js下载)
2016/05/05 Javascript
Vue过滤器的用法和自定义过滤器使用
2017/02/08 Javascript
ES6学习教程之对象的扩展详解
2017/05/02 Javascript
带你了解session和cookie作用原理区别和用法
2017/08/14 Javascript
Vue Promise的axios请求封装详解
2018/08/13 Javascript
Node.js模拟发起http请求从异步转同步的5种用法
2018/09/26 Javascript
js实现图片粘贴到网页
2019/12/06 Javascript
js实现数字跳动到指定数字
2020/08/25 Javascript
用js实现放大镜效果
2020/10/28 Javascript
antd vue table跨行合并单元格,并且自定义内容实例
2020/10/28 Javascript
Node.js文本文件BOM头的去除方法
2020/11/22 Javascript
JS算法教程之字符串去重与字符串反转
2020/12/15 Javascript
Python编程实现删除VC临时文件及Debug目录的方法
2017/03/22 Python
英国最大的滑板品牌选择:Route One
2019/09/22 全球购物
财务人员个人自荐信范文
2013/09/26 职场文书
初中三好学生自我鉴定
2014/04/07 职场文书
考试没考好检讨书(精选篇)
2014/11/16 职场文书
英语演讲开场白
2015/05/29 职场文书
回复函范文
2015/07/14 职场文书
热爱劳动主题班会
2015/08/14 职场文书
初中思想品德教学反思
2016/02/24 职场文书
职场新人刚入职工作总结该怎么写?
2019/05/15 职场文书
本地通过nginx配置反向代理的全过程记录
2021/03/31 Servers
浅谈golang package中init方法的多处定义及运行顺序问题
2021/05/06 Golang