背景:
我的用例中不可出现重复的记录,如:下订单,用户填好表单然后Submit,当用户网速较慢时,很可能会习惯性的刷新当前页,而刷新操作会导致再次POST,此时若不加判断直接入库必然导致用户后台增加N个订单。
解决思路:
Step 1:首先我们在进入表单填写页面时,对该页面(或view吧)随机生成一个校验字符串并存放于Session中,在页面form中新增一个hidden input来存放,以便提交时一起POST到服务器端;
Step 2:当POST时,服务器端将收到的校验串与Session中对应值比对,若相同则正常提交,否则跳转至指定的错误提示页面;需要注意的是当比对成功后,必须立即将该Session的值设置为空,这样才可保证页面再次POST时表单中的校验串就无法于Session中的空值比对成功。
实现:
为了方便使用,我们将上述思路写成一个decorator(装饰器). 当然也是为了符合DRY嘛;代码很简单就看中间那几行,需注意唯一的一个参数page_key,为了不跟多个表单页面发生Session key冲突。(补充一点:必须将表单填写页面的view同时使用@never_cache装饰,因为django默认将所有view都做缓存,当再次进入表单页时,就不会重新生成随机串,导致校验无故失败。。。)
#
coding:utf-8
try:
from functools import wraps
except ImportError:
from django.utils.functional import wraps # Python 2.4 fallback.
import random
from django.conf import settings
from django.utils.decorators import available_attrs
from django.utils.hashcompat import md5_constructor
if hasattr(random, 'SystemRandom'):
randrange = random.SystemRandom().randrange
else:
randrange = random.randrange
_MAX_CSRF_KEY = 18446744073709551616L # 2 << 63
def _get_new_submit_key():
return md5_constructor("%s%s" % (randrange(0, _MAX_CSRF_KEY), settings.SECRET_KEY)).hexdigest()
def anti_resubmit(page_key=''):
def decorator(view_func):
@wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request, *args, **kwargs):
if request.method == 'GET':
request.session['%s_submit' % page_key] = _get_new_submit_key()
print 'session:' + request.session.get('%s_submit' % page_key)
elif request.method == 'POST':
old_key = request.session.get('%s_submit' % page_key, '')
if old_key == '':
from django.http import HttpResponseRedirect
return HttpResponseRedirect('/page_expir')
request.session['%s_submit' % page_key] = ''
return view_func(request, *args, **kwargs)
return _wrapped_view
return decorator
使用示例:
@anti_resubmit(page_key='your_view')
def your_view(request):
'''若是表单填写页和POST的view不是同一个,則需在两个view上都使用anti_resubmit装饰器'''
pass #您可别跟着pass噢
2010-12-25 01:14 by 码农.KEN from http://www.cnblogs.com/ken-zhang/archive/2010/12/25/1916437.html
分享到:
相关推荐
在使用Django框架开发Web应用时,可能会遇到一个常见的问题,即在尝试通过POST方法提交表单时,收到“Forbidden (403) CSRF verification failed. Request aborted.”的错误。这个错误是由于Django的跨站请求伪造...
Angular ng-click 防止重复提交实例 Angular ng-click 防止重复提交实例是一个常见的问题,在 Angular 应用程序中,如果用户在短时间内多次点击按钮,可能会导致重复提交数据,从而影响应用程序的稳定性和性能。...
在`<a-select>`组件中,我们可以使用`v-model`和`v-decorator`来实现表单验证。`v-decorator`接受一个字段名和一个对象,对象中包含了初始值和验证规则。例如,对于**名称**字段,我们设置`required`规则以确保必填...
在上述的奇幻RPG游戏中,Decorator模式被用来实现武器的锻造过程,尤其是武器镶嵌宝石的功能。这个过程涉及到对基础武器(如剑)的扩展,以增加不同的属性和效果。 在没有引入Decorator模式之前,我们可能会使用...
在"基于JavaScript装饰器Decorator实现的通信库"——eventbus-cjs中,装饰器被用来简化组件间通信,特别是对于Vue和React这样的前端框架。EventBus是一种常见的实现组件间通信的方式,它可以作为一个轻量级的消息...
4. **Concrete Decorator(具体装饰者)**: 实现Decorator接口,提供具体的附加行为。在Java IO中,`BufferedInputStream`和`DataInputStream`就是装饰器,它们分别增加了缓冲和数据转换的功能。 **装饰模式的结构*...
《中文版django_book1》是一本关于Django框架的中文翻译书籍,涵盖了Django的各个方面,从基础到高级,帮助读者全面了解和掌握这个流行的Python web开发框架。书中的章节内容丰富,包括了以下主要知识点: 1. **第...
装饰器在Python编程语言中是一种强大的...通过理解和利用这个库,开发者可以更优雅地实现代码复用,提高程序的性能,并简化复杂的设计。在Python编程中,掌握装饰器及其库的使用,对于提升代码质量与可读性至关重要。
Decorator模式是设计模式中的一种结构型模式,它允许在运行时动态地给对象添加新的行为或职责,而不会破坏封装性。这种模式的核心思想是通过装饰类包装原对象,实现对原对象功能的扩展,同时保持与原接口的一致性。 ...
在本文中,我们将详细探讨基于`decorator-4.1.2`版本的装饰器库,以及如何在实际开发中有效地利用它。 首先,让我们了解装饰器的基本概念。装饰器本质上是一个接收函数作为参数并返回新函数的函数。它们通过插入...
这个"decorator python"模块是版本3.4.0的实现,其核心概念是通过函数来包装(即装饰)其他函数,以增强被装饰函数的行为。这个模块可能是由社区成员贡献并分享的,因此它属于"其他资源"类别。 在Python中,装饰器...
1. `decorator.py`: 这是核心的装饰器实现,包含了`@decorator`函数,以及其他辅助函数,如`functools.wraps`的实现,用于确保被装饰函数的元数据得以保留。 2. `decoratormodule.c`: 如果可用,这个C扩展模块可能会...
【Django框架中的英文单词】 Django是一个流行的Python Web开发框架,它的名字源自爵士乐手Django Reinhardt。本文将详细解释与Django框架相关的英文单词及其在编程语境下的含义。 1. **Django** ['dʒæŋɡəʊ ...
Ajax-django-ajax.zip,django应用程序的快速而简单的ajax库。包含ajax decorator、ajax中间件、快捷方式等。,ajax代表异步javascript和xml。它是多种web技术的集合,包括html、css、json、xml和javascript。它用于...
这是一个整合了多个技术框架的项目实例,主要涵盖了MyBatis3、SpringMVC4、AngularJS、MySQL数据库以及Decorator模式的应用。以下是对这些技术及其在项目中的应用进行的详细解释: 1. MyBatis3:MyBatis是一个优秀...
decorator-wechat,微信现代化(Nevolution decorator).zip
这样,当用户提交表单时,这个令牌会作为POST数据的一部分发送到服务器。 3. **中间件验证**:Django默认启用`CsrfViewMiddleware`中间件,它会检查POST请求中是否包含有效的CSRF令牌。如果请求缺少或令牌无效,...
这个库可能提供了方便的方式来确保类实现特定的协议,或者利用装饰器来检查和增强类的行为。 综上所述,`protocol_implements_decorator`库可能是为Python开发者设计的一个工具,帮助他们在分布式、云原生环境中,...
最近做了一个系统由于部分...Django Ratelimit is a ratelimiting decorator for Django views. http://huoche.7234.cn/images/jb51/anzpeymerkt.png?branch=master Code: https://github.com/jsocol/django-ratelimit
4. **具体装饰器(Concrete Decorator)**:实现了Decorator接口,并且在Component的基础上添加了新的行为。具体装饰器通常会包含对Component的实例化,并在其内部方法中调用Component的方法。 举个例子,假设我们...