0

我有一个名为 myClass 的类,它定义了 post() 和 get() 方法。

index.html中,我有一个带有调用 myClass.post() 的操作的表单,它从数据库中获取一些数据,设置几个变量并将用户发送到new.html

现在,new.html有一个调用 myClass.get() 的表单。

我希望 get() 方法知道我在 post() 中获得的变量的值。这是这里的重点。

我认为来自 new.html 的提交会创建一个单独的 myClass 实例,该实例由来自 index.html 的提交创建。

有没有办法以某种方式访问​​“发布实例”?

有解决方法吗?如果必须,是否有一种既定的方法可以将值从 post 发送到“new.html”并与 get-submit 一起发回?

更一般地说,我想我在网络编程时不了解我的实例的生命周期。在正常的交互环境中,我知道实例何时被创建和销毁,但是当我仅通过调用其方法来使用该类时,我不明白这一点。除非调用它们的方法,否则这些类是否会被实例化?

4

6 回答 6

3

你在说的是建立一个“会话”。也就是说,一种记住用户及其交易状态的方法。

有几种方法可以解决这个问题,所有这些方法都依赖于记住您首先在会话中的技术。

HTTP 没有为您提供任何帮助。您必须在服务器上找到保存会话状态的地方,并在客户端上找到记录会话标识的地方。两大技术是

  • 使用 cookie 来识别会话。无缝而沉默。

  • 在 URL 中使用查询字符串来标识会话。很明显,因为您?sessionid=SomeSessionGUID的 URL 中有一个。这暴露了很多,使书签变得烦人。清理完会话后,您仍然可以在人们的书签中看到此会话 ID。

  • 在有限的情况下,您还可以在表单中使用隐藏字段。这仅在您在每个页面上都有表单时才有效。并非总是如此。

以下是它在实践中的表现。

  1. 获取响应。检查标头中的 cookie。

    一个。没有饼干。初次使用者。创建会话。将其保存在某处(内存、文件、数据库)。将唯一 ID 放入 cookie。响应知道这是他们的第一次。

    湾。曲奇饼。最近来过这里。尝试获取 cookie。

    • F找到会话对象。使用 cookie 中的信息进行响应。

    • 德拉特。没有会话。老饼干。创建一个新的并表现得像这是他们的第一次访问。

  2. 发布响应。检查标头中的 cookie。

    一个。没有饼干。怎么回事?傻孩子。从我的草坪上离开!有人在 POST 上添加了书签或试图弄乱你的脑袋。像第一次 GET 一样响应。

    湾。曲奇饼。出色的。得到饼干。

    • 找到会话对象。在会话对象中找到你需要的东西。回应。

    • 德拉特。没有会话。老饼干。创建一个新的并像第一次 GET 一样响应。

您可以使用查询字符串而不是 cookie 来做同样的事情。或表单上的隐藏字段。

于 2008-12-11T11:24:44.733 回答
1

HTTP 是无状态的,因此您无法(内置)知道加载一个页面的用户是否与加载另一个页面的用户相同。此外,即使您确实知道这一点,例如,由于会话 cookie,您也无法判断他们加载后续页面的浏览器窗口是否与他们加载前一页面的浏览器窗口相同。用户可能有多个标签访问您的站点,并且您不希望一个页面的状态更改破坏另一个页面。

考虑到这一点,您最好的选择是在指向使用 GET 获取的页面的链接中包含查询参数,对要发送到“获取”页面的变量进行编码(确保它们不敏感,因为用户可以修改它们!)。然后你可以通过get请求中的self.request.GET来访问它们。

于 2008-12-11T09:18:31.447 回答
1

这不是如何管理实例的问题。因为 HTTP 是无状态的,所以您的程序实际上也是无状态的。(对于长时间运行的进程,如 GAE,可以采用其他方式,但我不确定您是否需要这种复杂性)

你没有提供任何代码,但我假设你得到一个 POST,然后你重定向到结果(这是一个 GET)。所以保存参数应该很容易:

def save_foo(request):
    if request.method == 'POST':
        save(request.POST)
        return HttpRedirect(reverse(
            'Some_Target',
            {'bar': 'baz', 'foo': request.POST['foo']}))
    else:
        # do something else

在 POST 的情况下,此视图会导致客户端向任何带有别名的 URL 发出 GET 请求Some_Target。这个 GET 将包含foo来自 POST 的参数。

此解决方案适用于单一视图。如果您在项目方面需要这种行为,您可以使用中间件。这一次缓存变量是有意义的。

有两点让我对这种方法有点不舒服:

  1. 混合 GET 和 POST 参数。GET 参数应该用于没有副作用的指令,例如过滤。POST 参数应该用于有副作用的指令,即修改数据。恕我直言,应避免将参数从 POST 移动到 get 。
  2. 如果我们需要持久性,使用对象实例(或我的示例中的函数范围)通常不是一个好主意。
    1. 如果它是具有较低保留需求的非敏感信息,cookies则可以选择。它们是客户端的一种持久性机制,因此您可以从请求中获取它们,除非您更改它们,否则它们将被保留(当然直到到期。)
    2. 如果您需要对保留进行更多控制,则应使用本地持久性机制。服务器缓存(任何类型)、文件系统、数据库......当然,您需要手动过滤每个用户。

无论如何,我都会避免缓存实例。

于 2008-12-11T07:12:22.140 回答
0

我不具体了解谷歌应用引擎,但通常情况如下:

服务器将具有某种线程池。每次向服务器发送 http 请求时,都会从池中选择或创建一个线程。

在该线程中,将创建某种控制器对象的实例。该对象将决定如何处理请求(例如实例化其他类和预处理 http 请求参数)。通常,这个对象是 Web 框架的核心。请求参数也是浏览器每次重新发送的(服务器无法猜测浏览器想要什么)。

Web 服务器通常具有永久或会话状态的对象的状态存储。会话由唯一用户(通常由 url 中的 cookie 或 GUID)表示,该用户在一定时间后过期。

现在,在您的情况下,您需要从第一个函数中获取值,将其存储在会话存储中,然后在第二个函数中,从会话存储中获取这些值。

另一种解决方案是将项目作为您从第一个函数生成的 HTML 中的 url 参数发送回页面,然后您将“照常”从第二个函数中获取这些项目。

于 2008-12-11T04:09:50.213 回答
0

好的——谢谢大家。

我会尽快尝试其中的一些想法,然后回复大家。

似乎我可以通过从数据存储中进行大量写入和读取来解决这些问题*,但我认为可能有一种更简单的方法来保留该类的实例(我正在尝试使用我的已知技术一个我还没有完全掌握的网络框架)。

*例如,根据 POST 中的数据创建唯一记录,并让一些变量“标记”。这是一个不好的做法吗?

于 2008-12-11T18:02:19.237 回答
0

为什么不直接使用 memcache 临时存储变量,然后重定向到 POST URL?这似乎是最简单的解决方案。

于 2008-12-11T09:41:01.467 回答