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实现马耳可夫链算法实例分析
May 20 Python
python在Windows下安装setuptools(easy_install工具)步骤详解
Jul 01 Python
Python在信息学竞赛中的运用及Python的基本用法(详解)
Aug 15 Python
Python 反转字符串(reverse)的方法小结
Feb 20 Python
查找python项目依赖并生成requirements.txt的方法
Jul 10 Python
Python二进制串转换为通用字符串的方法
Jul 23 Python
Python使用get_text()方法从大段html中提取文本的实例
Aug 27 Python
python 通过视频url获取视频的宽高方式
Dec 10 Python
Selenium 滚动页面至元素可见的方法
Mar 18 Python
利用python控制Autocad:pyautocad方式
Jun 01 Python
python 两种方法修改文件的创建时间、修改时间、访问时间
Sep 26 Python
python正则表达式re.match()匹配多个字符方法的实现
Jan 27 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
PHP动态柱状图实现方法
2015/03/30 PHP
Code:loadScript( )加载js的功能函数
2007/02/02 Javascript
javascript 检测浏览器类型和版本的代码
2009/09/15 Javascript
js实现简单的星级选择器提交效果适用于评论等
2013/10/18 Javascript
JQueryiframe页面操作父页面中的元素与方法(实例讲解)
2013/11/19 Javascript
浅析jquery ajax异步调用方法中不能给全局变量赋值的原因及解决方法
2014/01/10 Javascript
js倒计时抢购实例
2015/12/20 Javascript
基于javascript实现全屏漂浮广告
2016/03/31 Javascript
详解原生JavaScript实现jQuery中AJAX处理的方法
2016/05/10 Javascript
JQuery异步加载PartialView的方法
2016/06/07 Javascript
在微信、支付宝、百度钱包实现点击返回按钮关闭当前页面和窗口的方法
2016/08/05 Javascript
JavaScript实现瀑布流以及加载效果
2017/02/11 Javascript
JS优化与惰性载入函数实例分析
2017/04/06 Javascript
原JS实现banner图的常用功能
2017/06/12 Javascript
解决ionic和angular上拉加载的问题
2017/08/03 Javascript
Vue-cli Eslint在vscode里代码自动格式化的方法
2018/02/23 Javascript
js动态设置select下拉菜单的默认选中项实例
2018/08/21 Javascript
Vuex 在Vue 组件中获得Vuex 状态state的方法
2018/08/27 Javascript
Openlayers实现点闪烁扩散效果
2020/09/24 Javascript
javascript实现移动端轮播图
2020/12/09 Javascript
js实现简单的倒计时
2021/01/28 Javascript
python生成日历实例解析
2014/08/21 Python
Python数据类型详解(四)字典:dict
2016/05/12 Python
python实现八大排序算法(1)
2017/09/14 Python
解决python3 requests headers参数不能有中文的问题
2019/08/21 Python
python实现批量处理将图片粘贴到另一张图片上并保存
2019/12/12 Python
python3+opencv生成不规则黑白mask实例
2020/02/19 Python
HTML5 canvas基本绘图之图形组合
2016/06/27 HTML / CSS
Reebok俄罗斯官方网上商店:购买锐步运动服装和鞋子
2016/09/26 全球购物
英语专业学子个人的自我评价
2013/10/02 职场文书
音乐系毕业生自荐信
2013/10/27 职场文书
简历自荐信
2013/12/02 职场文书
一年级学生评语大全
2014/04/21 职场文书
2014年小学国庆节活动方案
2014/09/16 职场文书
2015年林业工作总结
2015/05/14 职场文书
2016年度农村党员干部主题教育活动总结
2016/04/06 职场文书