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 相关文章推荐
可用于监控 mysql Master Slave 状态的python代码
Feb 10 Python
python类定义的讲解
Nov 01 Python
Python 26进制计算实现方法
May 28 Python
python追加元素到列表的方法
Jul 28 Python
python 字典中文key处理,读取,比较方法
Jul 06 Python
OpenCV+python手势识别框架和实例讲解
Aug 03 Python
pandas通过索引进行排序的示例
Nov 16 Python
elasticsearch python 查询的两种方法
Aug 04 Python
Python人工智能之路 之PyAudio 实现录音 自动化交互实现问答
Aug 13 Python
python3使用GUI统计代码量
Sep 18 Python
浅谈python print(xx, flush = True) 全网最清晰的解释
Feb 21 Python
python等差数列求和公式前 100 项的和实例
Feb 25 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
一些不错的js函数ajax
2008/08/20 Javascript
在UpdatePanel内jquery easyui效果失效的解决方法
2010/04/11 Javascript
JQuery FlexiGrid的asp.net完美解决方案 dotNetFlexGrid-.Net原生的异步表格控件
2010/09/12 Javascript
js 数据类型转换总结笔记
2011/01/17 Javascript
js监听滚动条滚动事件使得某个标签内容始终位于同一位置
2014/01/24 Javascript
JS实现图片无间断滚动代码汇总
2014/07/30 Javascript
jQuery实现图片左右滚动特效
2020/04/20 Javascript
实例讲解javascript注册事件处理函数
2016/01/09 Javascript
javascript嵌套函数和在函数内调用外部函数的区别分析
2016/01/31 Javascript
jQuery给div,Span, a ,button, radio 赋值与取值
2016/06/24 Javascript
es6系列教程_ Map详解以及常用api介绍
2017/09/25 Javascript
Vue底层实现原理总结
2018/02/17 Javascript
JS实现显示当前日期的实例代码
2018/07/03 Javascript
JavaScript的词法结构精华篇
2018/10/17 Javascript
vue mounted 调用两次的完美解决办法
2018/10/29 Javascript
Javascript Worker子线程代码实例
2020/02/20 Javascript
vue实现自定义多选按钮
2020/07/16 Javascript
Python struct.unpack
2008/09/06 Python
Python中使用Flask、MongoDB搭建简易图片服务器
2015/02/04 Python
Django验证码的生成与使用示例
2017/05/20 Python
Pycharm编辑器技巧之自动导入模块详解
2017/07/18 Python
python打包exe开机自动启动的实例(windows)
2019/06/28 Python
python requests使用socks5的例子
2019/07/25 Python
Python zip函数打包元素实例解析
2019/12/11 Python
将 Ubuntu 16 和 18 上的 python 升级到最新 python3.8 的方法教程
2020/03/11 Python
CSS3 border-radius圆角的实现方法及用法详解
2020/09/14 HTML / CSS
html Table 表头固定的实现
2019/01/22 HTML / CSS
夏尔巴人登珠峰品牌:Sherpa Adventure Gear
2018/02/08 全球购物
电影T恤、80年代T恤和80年代服装:TV Store Online
2020/01/05 全球购物
新三好学生主要事迹
2014/01/23 职场文书
铣床操作工岗位职责
2014/06/13 职场文书
优秀教师申报材料
2014/12/16 职场文书
网聊搭讪开场白
2015/05/28 职场文书
Python数据分析之pandas函数详解
2021/04/21 Python
Python自动化爬取天眼查数据的实现
2021/06/15 Python
javascript之Object.assign()的痛点分析
2022/03/03 Javascript