• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell
您的位置:首页 > 脚本语言 >python > 使用Python的Django框架实现事务交易管理的教程

使用Python的Django框架实现事务交易管理的教程

作者:goldensun 字体:[增加 减小] 来源:互联网

goldensun 通过本文主要向大家介绍了python django框架,python安装django,python.django,python django教程,python web django等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

 如果你花费了很多的时间去进行Django数据库事务处理的话,你将会了解到这是让人晕头转向的。

在过去,只是提供了简单的基础文档,要想清楚知道它是怎么使用的,还必须要通过创建和执行Django的事务处理。

这里有众多的Django事务处理的名词,例如:commit_on_success , commit_manually , commit_unless_maneged,rollback_unless_managed,enter_transaction_management,leace_transaction_management,这些只是其中的一部分而已。

最让人感到幸运的是,Django 1.6版本发布后。现在你可以紧紧使用几个函数就可以实现事务处理了,在我们进入学习这些函数的几秒之前。首先,我们要明确下面这些问题:

  •     什么是事务处理呢?
  •     Django 1.6中的出现了那些新的事物处理优先权?

在进入“要怎么才是Django 1.6版本中正确的事务处理”之前,请先了解一下下面的详细案例:

    带状案例

    事务

  •             推荐的方式
  •             使用分隔符
  •             每一个HTTP请求事务

    保存点

    嵌套的事务


事务是什么?

根据SQL-92所说,"一个SQL事务(有时简称为事务)是一个可以原子性恢复的SQL语句执行序列"。换句话说,所有的SQL语句一起执行和提交。同样的,当回滚时,所有语句也一并回滚。

例如:
 

# START
note = Note(title="my first note", text="Yay!")
note = Note(title="my second note", text="Whee!")
address1.save()
address2.save()
# COMMIT
</div>

所以一个事务是 数据库中单个的工作单元。它是由一个start transaction开始和一个commit或者显式的rollback结束。

Django 1.6之前的事务管理有什么问题?

为了完整地回答这个问题,我们必须阐述一下事务在数据库、客户端以及Django中是如何处理的。

数据库

数据库中的每一条语句都运行在一个事务中,这个事务甚至可以只包含一条语句。

几乎所有的数据库都有一个AUTOCOMMIT设置,通常它被默认设置为True。AUTOCOMMIT将所有语句包装到一个事务里,只要语句成功执行,这个事务就立即被提交。当然你也可以手动调用START_TRANSACTION,它会暂时将AUTOCOMMIT挂起,直到你调用COMMIT_TRANSACTION或者ROLLBACK。

然后,这种方式将会使AUTOCOMMIT设置的作用于每条语句后的隐式提交失效。


然而,有诸如像sqlite3和mysqldb的python客户端库,它允许python程序与数据库本身相连接。这些库遵循一套如何访问与查询数据库的标准。该DB API 2.0标准,被描述在PEP 249之中。虽然它可能让人阅读稍干一些。一个重要带走的是,在PEP 249状态之中,默认数据库应该关闭自动提交功能。

这明显与数据库内发生了什么矛盾冲突:

  •     数据库语句总是要在一个事务中运行。此数据库一般会为你打开自动提交功能。
  •     不过,根据PEP 249,这不应该发生。
  •     客户端库必须反映在数据库之中发生了什么?但由于他们不允许默认打开自动提交功能。他们只是简单地在一个事务中包裹sql语句。就像数据库。

好啦,在我身边呆久一些吧。

 

Django

进入Django,Django也有关于事务处理的话要说。在Django 1.5和更早的版本。当你写数据到数据库时,Django基本上是运行一个开放的事务和自动提交该事务功能。所以每次你所称谓的像诸如model.save() 或者model.update()的东西,Django生成相应的sql语句,并提交该事务。

也有在Django 1.5和更早的版本,它是建议你使用TransactionMiddleware绑定http请求事务。每个请求提供了一个事务。如果返回的响应没有异常,Django会提交此事务。但如果你的视图功能抛出一个错误,回滚将被调用。这实际上说明,它关闭了自动提交功能。如果你想要标准化,数据库级别自动提交风格式的事务管理,你必须管理你自己的交易-通常是通过使用事务装饰你的视图功能,例如@transaction.commit_manually,或者@transaction.commit_on_success.

吸一口气,或者两口。


这意味着什么?

是啊,在那儿有许多事情要做,而事实证明,大多数开发者正需要这个标准数据库级的自动提交功能-有意义的事务往往是留在幕后处理的。做你自己的事,直到你需要手动调整他们。

在Django 1.6版本之中,什么是正确关于事务管理呢?

现在,欢迎来到Django 1.6.尽力忘掉一切吧,我们只是谈论而已,只是记得在Django 1.6中,你可以使用数据库,需要时可以手动自动提交和管理事务。从本质上来说,我们有一个更简单的模型,基本上是要把设计什么样的数据库摆在首位。

好啦!大功告成,让我们写代码吧?

 

Stripe案例

下面,我们使用处理一个用户注册的例子,调用了Stripe来处理信用卡进程。
 

def register(request):
  user = None
  if request.method == 'POST':
    form = UserForm(request.POST)
    if form.is_valid():
 
      customer = Customer.create("subscription",
       email = form.cleaned_data['email'],
       description = form.cleaned_data['name'],
       card = form.cleaned_data['stripe_token'],
       plan="gold",
      )
 
      cd = form.cleaned_data      
      try:
        user = User.create(cd['name'], cd['email'], cd['password'],
          cd['last_4_digits'])
 
        if customer:
          user.stripe_id = customer.id
          user.save()
        else:
          UnpaidUsers(email=cd['email']).save()
 
      except IntegrityError:
        form.addError(cd['email'] + ' is already a member')
      else:
        request.session['user'] = user.pk
        return HttpResponseRedirect('/')
 
  else:
   form = UserForm()
 
  return render_to_response(
    'register.html',
    {
     'form': form,
     'months': range(1, 12),
     'publishable': settings.STRIPE_PUBLISHABLE,
     'soon': soon(),
     'user': user,
     'years': range(2011, 2036),
    },
    context_instance=RequestContext(request)
  )
</div>

例子首先调用了Customer.create,实际上就是调用Stripe来处理信用卡进程,然后我们创建一个新用户。如果我们得到来自Stripe的响应,我们就用stripe_id更新新创建的用户。如果我们没有得到响应(Stripe已关闭),我们将用新创建用户的email向UnpaidUsers表增加一个新条目,这样我们可以让他们稍后重试他们信用卡信息。


思路是这样的:如果Stripe没有响应,用户依然可以注册,然后开始使用我们的网站。我们将在稍后的时候让用户提供信用卡的信息。

“我明白这是一个特殊的例子,并且这也不是我想完成的功能的方式,但是它的目的是展示交易”

考虑交易,牢记住在Django1.6中提供了对于数据库的“AUTOCOMMIT”功能。接下来看一下数据库相关的代码:
 

cd = form.cleaned_data
try:
  user = User.create(cd['name'], cd['email'], cd['password'], cd['last_4_digits'])
 
  if customer:
    user.stripe_id = customer.id
    user.save()
  else:
    UnpaidUsers(email=cd['email']).save()
 
except IntegrityError:
</div>

你能发现问题了吗?如果“UnpaidUsers(email=cd['email']).save()” 运行失败,会发生什么?

有一个用户,注册了系统;然后系统认为已经核对过信用卡了。但是事实上,系统并没有核对过。

我们仅仅想得到其中一种结果:

1.在数据库中创建了用户,并有了stripe_id

2.在数据库中创建了用户,但是没有stripe_id。同时在相关的“UnpaidUsers”行,存有相同的邮件地址

这就意味着,我们想要的是分开的数据库语句头完成任务或者回滚。这个例子很好的说明了这个交易。


首先,我们写一些测试用例来验证事情是否按照我们想象的方式运行: 
 

@mock.patch('payments.models.UnpaidUsers.save', side_effect = IntegrityError)
def test_registering_user_when_strip_is_down_all_or_nothing(self, save_mock):
 
  #create the request used to test the view
  self.request.session = {}
  self.request.method='POST'
  self.request.POST = {'email' : 'python@rocks.com',
             'name' : 'pyRock',
             'stripe_token' : '...',
             'last_4_digits' : '4242',
             'password' : 'bad_password',
             'ver_password' : 'bad_password',
            } 
  


 

您可能想查找下面的文章:

  • Python之Web框架Django项目搭建全过程
  • Python之Web框架Django项目搭建全过程
  • python django事务transaction源码分析详解
  • python+django快速实现文件上传
  • Python+django实现简单的文件上传
  • Python+django实现简单的文件上传
  • 搭建Python的Django框架环境并建立和运行第一个App的教程
  • 搭建Python的Django框架环境并建立和运行第一个App的教程
  • Python的Django框架中消息通知的计数器实现教程
  • Python的Django框架中消息通知的计数器实现教程

相关文章

  • 浅谈Python的Django框架中的缓存控制
  • 把MySQL表结构映射为Python中的对象的教程
  • 如何准确判断请求是搜索引擎爬虫(蜘蛛)发出的请求
  • Python 中的 else详解
  • 浅析Python编写函数装饰器
  • 一个计算身份证号码校验位的Python小程序
  • 用Python编写web API的教程
  • Python urlopen()函数 示例分享
  • Python中的变量和作用域详解
  • 在Python中使用Mako模版库的简单教程

文章分类

  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell

最近更新的内容

    • Python Tkinter基础控件用法
    • Python实现优先级队列结构的方法详解
    • Python中文分词实现方法(安装pymmseg)
    • Python中的推导式使用详解
    • python中pandas.DataFrame的简单操作方法(创建、索引、增添与删除)
    • python正则表达式中的括号匹配问题
    • Python实例之wxpython中Frame使用方法
    • Python设置默认编码为utf8的方法
    • Python中Django发送带图片和附件的邮件
    • python使用socket连接远程服务器的方法

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有