`
54yuri
  • 浏览: 28212 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【转帖】利用decorator实现Django表单防重复提交

阅读更多
背景:
  我的用例中不可出现重复的记录,如:下订单,用户填好表单然后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
分享到:
评论

相关推荐

    DJANGOPOST提交问题解决2.pdf

    在使用Django框架开发Web应用时,可能会遇到一个常见的问题,即在尝试通过POST方法提交表单时,收到“Forbidden (403) CSRF verification failed. Request aborted.”的错误。这个错误是由于Django的跨站请求伪造...

    angular ng-click防止重复提交实例

    Angular ng-click 防止重复提交实例 Angular ng-click 防止重复提交实例是一个常见的问题,在 Angular 应用程序中,如果用户在短时间内多次点击按钮,可能会导致重复提交数据,从而影响应用程序的稳定性和性能。...

    【JavaScript源代码】antd+vue实现动态验证循环属性表单的思路.docx

    在`&lt;a-select&gt;`组件中,我们可以使用`v-model`和`v-decorator`来实现表单验证。`v-decorator`接受一个字段名和一个对象,对象中包含了初始值和验证规则。例如,对于**名称**字段,我们设置`required`规则以确保必填...

    设计模式之 Decorator模式和代码实现

    在上述的奇幻RPG游戏中,Decorator模式被用来实现武器的锻造过程,尤其是武器镶嵌宝石的功能。这个过程涉及到对基础武器(如剑)的扩展,以增加不同的属性和效果。 在没有引入Decorator模式之前,我们可能会使用...

    基于JavaScript装饰器Decorator实现的通信库

    在"基于JavaScript装饰器Decorator实现的通信库"——eventbus-cjs中,装饰器被用来简化组件间通信,特别是对于Vue和React这样的前端框架。EventBus是一种常见的实现组件间通信的方式,它可以作为一个轻量级的消息...

    java Decorator装饰模式例子

    4. **Concrete Decorator(具体装饰者)**: 实现Decorator接口,提供具体的附加行为。在Java IO中,`BufferedInputStream`和`DataInputStream`就是装饰器,它们分别增加了缓冲和数据转换的功能。 **装饰模式的结构*...

    中文版django_book1

    《中文版django_book1》是一本关于Django框架的中文翻译书籍,涵盖了Django的各个方面,从基础到高级,帮助读者全面了解和掌握这个流行的Python web开发框架。书中的章节内容丰富,包括了以下主要知识点: 1. **第...

    Decorator-3.4.0

    装饰器在Python编程语言中是一种强大的...通过理解和利用这个库,开发者可以更优雅地实现代码复用,提高程序的性能,并简化复杂的设计。在Python编程中,掌握装饰器及其库的使用,对于提升代码质量与可读性至关重要。

    C++ Decorator模式

    Decorator模式是设计模式中的一种结构型模式,它允许在运行时动态地给对象添加新的行为或职责,而不会破坏封装性。这种模式的核心思想是通过装饰类包装原对象,实现对原对象功能的扩展,同时保持与原接口的一致性。 ...

    decorator-4.1.2.rar ,亲测可用

    在本文中,我们将详细探讨基于`decorator-4.1.2`版本的装饰器库,以及如何在实际开发中有效地利用它。 首先,让我们了解装饰器的基本概念。装饰器本质上是一个接收函数作为参数并返回新函数的函数。它们通过插入...

    decorator python(decorator-3.4.0.tar.gz).rar

    这个"decorator python"模块是版本3.4.0的实现,其核心概念是通过函数来包装(即装饰)其他函数,以增强被装饰函数的行为。这个模块可能是由社区成员贡献并分享的,因此它属于"其他资源"类别。 在Python中,装饰器...

    decorator-4.1.2.tar.gz

    1. `decorator.py`: 这是核心的装饰器实现,包含了`@decorator`函数,以及其他辅助函数,如`functools.wraps`的实现,用于确保被装饰函数的元数据得以保留。 2. `decoratormodule.c`: 如果可用,这个C扩展模块可能会...

    Django框架中的英文单词.docx

    【Django框架中的英文单词】 Django是一个流行的Python Web开发框架,它的名字源自爵士乐手Django Reinhardt。本文将详细解释与Django框架相关的英文单词及其在编程语境下的含义。 1. **Django** ['dʒæŋɡəʊ ...

    Ajax-django-ajax.zip

    Ajax-django-ajax.zip,django应用程序的快速而简单的ajax库。包含ajax decorator、ajax中间件、快捷方式等。,ajax代表异步javascript和xml。它是多种web技术的集合,包括html、css、json、xml和javascript。它用于...

    mybatis3+springmvc4+angularjs+mysql+decorator实例

    这是一个整合了多个技术框架的项目实例,主要涵盖了MyBatis3、SpringMVC4、AngularJS、MySQL数据库以及Decorator模式的应用。以下是对这些技术及其在项目中的应用进行的详细解释: 1. MyBatis3:MyBatis是一个优秀...

    decorator-wechat,微信现代化(Nevolution decorator).zip

    decorator-wechat,微信现代化(Nevolution decorator).zip

    Django CSRF跨站请求伪造防护过程解析

    这样,当用户提交表单时,这个令牌会作为POST数据的一部分发送到服务器。 3. **中间件验证**:Django默认启用`CsrfViewMiddleware`中间件,它会检查POST请求中是否包含有效的CSRF令牌。如果请求缺少或令牌无效,...

    PyPI 官网下载 | protocol_implements_decorator-0.3.1.tar.gz

    这个库可能提供了方便的方式来确保类实现特定的协议,或者利用装饰器来检查和增强类的行为。 综上所述,`protocol_implements_decorator`库可能是为Python开发者设计的一个工具,帮助他们在分布式、云原生环境中,...

    Django 限制访问频率的思路详解

    最近做了一个系统由于部分...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

    装饰器模式[Decorator]

    4. **具体装饰器(Concrete Decorator)**:实现了Decorator接口,并且在Component的基础上添加了新的行为。具体装饰器通常会包含对Component的实例化,并在其内部方法中调用Component的方法。 举个例子,假设我们...

Global site tag (gtag.js) - Google Analytics