在页面加载时加载时间戳并将其与表单提交时的时间戳进行比较

时间:2014-08-14 19:06:53

标签: javascript jquery python django datetime

我在我的应用程序中开发了一个反垃圾邮件时间陷阱(是的,我知道它不会100%有效,但这是权宜之计)这样做:

1)加载页面时,使用JavaScript填充带有时间戳的隐藏输入:

var timestamp = new Date().getTime() / 1000;

2)当表单被POST时,使用Python视图根据当前时间检查此时间戳 - 如果页面加载后不到5秒,则退回异常:

import datetime

feedback_timestamp = request.POST['feedback_timestamp'].strip()
current_timestamp = datetime.datetime.now().timestamp()

if current_timestamp - float(feedback_timestamp) < 5:
    raise Exception("Submitted too quickly after loading!")

这在我的本地开发服务器上工作正常(即它会强制您等待5秒,否则会抛出异常)。但是,我注意到,一旦我将它加载到我的生产服务器上,即使我在加载后立即提交表单,时间戳也相互间隔约30秒。似乎JavaScript函数从本地用户那里获取时间,而Python代码从服务器获取它,因此,如果它们不同步,它将无法正确触发。

我的问题是:如何从服务器而不是本地计算机获取初始时间戳?是否有一个JavaScript函数可以做到这一点?或者我是否需要使用Python后端填充隐藏的输入?

如果是后者,事情有点复杂,因为这一切都是在我的base.html中完成的,它永远不会被我的任何视图直接加载(即它用于扩展我使用的许多其他视图)。如何在不使用与页面关联的视图的情况下从Python后端提取值?

2 个答案:

答案 0 :(得分:1)

如果您不想在视图中执行逻辑,可以使用上下文处理器将变量发送到模板:

def add_timestamp_context(request):
    return {'current_time': datetime.datetime.now()}

或类似的东西。有关详细信息,请参阅here。如文档中所述,您需要将新功能添加到TEMPLATE_CONTEXT_PROCESSORS中的settings.py变量中。

您还应该注意,发送到模板的所有变量都可以在base.html中使用。因此,您可以从关联的视图将变量发送到模板,即使前端逻辑位于base.html文件中,它也可以正常工作。

在我看来,最好的解决方案是计算前端而不是后端的两个邮票。

答案 1 :(得分:1)

您可以使用上下文处理器为每个模板添加时间戳上下文变量。您的上下文处理器是一个简单的Python函数,它接受HttpRequest参数并返回一个字典,该字典将被添加到您的上下文字典中。

您的功能可能如下所示:

def timestamp(request):
    ctx = {
        'timestamp': timezone.now()
    }
    return ctx

然后,在settings.py中将您的功能添加到TEMPLATE_CONTEXT_PROCESSORS

TEMPLATE_CONTEXT_PROCESSORS = (
    ...,
    'path.to.function.context_processors.timestamp',
)

就是这样! See further documentation here.