博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
django中F函数的应用
阅读量:5298 次
发布时间:2019-06-14

本文共 5238 字,大约阅读时间需要 17 分钟。

mysite/feed/models.py

 

#!/usr/bin/python # -*- coding: utf-8 -*- from django.db import models from django.db.models import F     class Account(models.Model): """ 账户"""     balance = models.DecimalField('余额', max_digits=19, decimal_places=4)     version = models.IntegerField('版本号')     created = models.DateTimeField('创建时间', auto_now_add=True)     updated = models.DateTimeField('最后修改时间', auto_now=True) def add(self, amount): """ 增加金额"""         self.balance += amount         self.save()         self = self.__class__.objects.get(pk=self.id)         TradeRecord(             account=self,             amount=amount,             balance=self.balance,         ).save() return self.balance def f_add(self, amount): """ F函数"""         self.balance = F('balance') + amount         self.save()         self = self.__class__.objects.get(pk=self.id)         TradeRecord(             account=self,             amount=amount,             balance=self.balance,         ).save() return self.balance def lock_add(self, amount): """ 乐观锁"""         self.balance += amount         self.version += 1         new_self = self.__class__.objects.get(pk=self.id) print self.version, new_self.version if self.version > new_self.version:             self.save()             TradeRecord(                 account=self,                 amount=amount,                 balance=self.balance,             ).save() return self.balance return False class TradeRecord(models.Model): """ 交易明细"""     account = models.ForeignKey(Account)     amount = models.DecimalField('交易金额', max_digits=19, decimal_places=4)     balance = models.DecimalField('交易后余额', max_digits=19, decimal_places=4)     created = models.DateTimeField('创建时间', auto_now_add=True)     updated = models.DateTimeField('最后修改时间', auto_now=True)

终端1

 

>>> from mysite.feed.models import * >>> account = Account.objects.get(pk=1) >>> account.balance Decimal("9.0000") >>> account.add(1) Decimal("10.0000") >>> account.balance Decimal("10.0000") >>>

终端2

 

>>> from mysite.feed.models import * >>> account = Account.objects.get(pk=1) >>> account.balance Decimal("10.0000") >>> account.add(1) Decimal("11.0000") >>> account.balance Decimal("11.0000") >>>

终端1

 

>>> account.balance Decimal("10.0000") >>> account.add(1) Decimal("11.0000") >>> account.balance Decimal("11.0000") >>>

初始值为9,在终端1进行了两次加1,终端2进行了一次加1操作,期望值为12,实际值为11。因为在终端1进行第二次加1操作时,余额已经读出为10.

使用F函数

终端2

 

>>> from django.db.models import F >>> account.balance Decimal("11.0000") >>> account.balance = F('balance') + 1 >>> account.save() >>> account.balance 
>>> account = Account.objects.get(pk=1) >>> account.balance Decimal("12.0000") >>>

终端1

 

>>> from django.db.models import F >>> account.balance Decimal("11.0000") >>> account.balance = F('balance') + 1 >>> account.save() >>> account.balance 
>>> account = Account.objects.get(pk=1) >>> account.balance Decimal("13.0000") >>>

在终端1执行时,虽然已经读出balance的值为11,但是加1后的结果仍然是13。可以看出使用F函数进行累加,在执行Save时,始终会去取数据库中最新的值,而不是已经取出的值。所以我们可以用F函数改写add函数,来保证并发执行时数据的正确性。

我们可以看到Django ORM在处理这两种累加在实际执行的SQL语句上的差异。

from django.db.models import F from mysite.feed.models import * account = Account.objects.get(pk=1) account 
account.balance Decimal("0.0000") from django.db import connection connection.queries

[{'time': '0.000', 'sql': u'SELECT `feed_account`.`id`, `feed_account`.`balance`, `feed_account`.`version`, `feed_account`.`created`, `feed_account`.`updated` FROM `feed_account` WHERE `feed_account`.`id` = 1 '}]

 

account.balance += 1 connection.queries

[{'time': '0.000', 'sql': u'SELECT `feed_account`.`id`, `feed_account`.`balance`, `feed_account`.`version`, `feed_account`.`created`, `feed_account`.`updated` FROM `feed_account` WHERE `feed_account`.`id` = 1 '}]

account.save() connection.queries

[{'time': '0.000', 'sql': u'SELECT `feed_account`.`id`, `feed_account`.`balance`, `feed_account`.`version`, `feed_account`.`created`, `feed_account`.`updated` FROM `feed_account` WHERE `feed_account`.`id` = 1 '}, {'time': '0.000', 'sql': u'SELECT (1) AS `a` FROM `feed_account` WHERE `feed_account`.`id` = 1 LIMIT 1'}, {'time': '0.000', 'sql': u'UPDATE `feed_account` SET`balance` = 1.0000, `version` = 1, `created` = 2011-06-10 14:20:36, `updated` = 2011-06-10 16:00:52 WHERE `feed_account`.`id` = 1 '}]

 

account.balance = F('balance') + 1 account.save() connection.queries

[{'time': '0.000', 'sql': u'SELECT `feed_account`.`id`, `feed_account`.`balance`, `feed_account`.`version`, `feed_account`.`created`, `feed_account`.`updated` FROM `feed_account` WHERE `feed_account`.`id` = 1 '}, {'time': '0.000', 'sql': u'SELECT (1) AS `a` FROM `feed_account` WHERE `feed_account`.`id` = 1 LIMIT 1'}, {'time': '0.000', 'sql': u'UPDATE `feed_account` SET `balance` = 1.0000, `version` = 1, `created` = 2011-06-10 14:20:36, `updated` = 2011-06-10 16:00:52 WHERE `feed_account`.`id` = 1 '}, {'time': '0.000', 'sql': u'SELECT (1) AS `a` FROM `feed_account` WHERE `feed_account`.`id` = 1 LIMIT 1'}, {'time': '0.000', 'sql': u'UPDATE `feed_account` SET `balance` = `feed_account`.`balance` + 1, `version` = 1, `created` = 2011-06-10 14:20:36, `updated` = 2011-06-10 16:02:21 WHERE `feed_account`.`id` = 1 '}]

 

参考资料:

 

转载于:https://www.cnblogs.com/crafter/archive/2011/11/20/2262906.html

你可能感兴趣的文章
Spring面试题
查看>>
窥视SP2010--第一章节--SP2010开发者路线图
查看>>
MVC,MVP 和 MVVM 的图示,区别
查看>>
C语言栈的实现
查看>>
代码为什么需要重构
查看>>
TC SRM 593 DIV1 250
查看>>
SRM 628 DIV2
查看>>
2018-2019-2 20165314『网络对抗技术』Exp5:MSF基础应用
查看>>
Python-S9-Day127-Scrapy爬虫框架2
查看>>
使用gitbash来链接mysql
查看>>
SecureCRT的使用方法和技巧(详细使用教程)
查看>>
右侧导航栏(动态添加数据到list)
查看>>
81、iOS本地推送与远程推送详解
查看>>
虚拟DOM
查看>>
uva 11468 Substring
查看>>
自建数据源(RSO2)、及数据源增强
查看>>
BootStrap2学习日记2--将固定布局换成响应式布局
查看>>
关于View控件中的Context选择
查看>>
2018icpc徐州OnlineA Hard to prepare
查看>>
Spark的启动进程详解
查看>>