【问题标题】:How do you do something after you render the view? (Django)渲染视图后如何做某事? (姜戈)
【发布时间】:2009-07-04 02:16:36
【问题描述】:

我想在使用

渲染视图后做一些事情
return render_to_response()

信号是唯一的方法吗?我需要编写自定义信号还是 request_finished 给了我足够的信息?基本上我需要知道渲染了哪个页面,然后执行相应的操作。

谢谢。

来自评论的更新:我不想推迟页面的渲染,所以我想先渲染页面然后执行操作。

【问题讨论】:

  • 这似乎落后了。你知道你将要渲染哪个页面。只做动作。为什么不能简单地在视图函数中插入额外的动作?请提供一些关于您正在尝试做什么的提示。
  • 我不想拖住页面的渲染,所以我想先渲染页面然后做动作
  • @rick:请不要评论您自己的问题,请用其他事实更新您的问题。

标签: python django


【解决方案1】:

您生成一个单独的线程并让它执行操作。

t = threading.Thread(target=do_my_action, args=[my_argument])
# We want the program to wait on this thread before shutting down.
t.setDaemon(False)
t.start()

这将导致“do_my_action(my_argument)”在第二个线程中执行,即使在您发送 Django 响应并终止初始线程后,该线程仍将继续工作。例如,它可以在不延迟响应的情况下发送电子邮件。

【讨论】:

  • 我试过这个实现。显然,即使它的任务尚未完成,启动的第二个线程也会终止。就我而言,它正在更新几个数据库条目
【解决方案2】:

如果您有一个长时间运行的流程,您有两个简单的选择。

  1. 在发送响应页面之前生成一个子进程。

  2. 创建一个“后台服务守护进程”并将工作请求传递给它。

这一切都在 Django 之外。您使用subprocess 或其他IPC 方法与其他进程通信。

【讨论】:

  • 同意——我会使用某种 IPC 来使这个模块化和网络服务器中立。您可能不想在响应发送后侵入 Django 内部来执行操作。
【解决方案3】:

执行此操作的常用方法是使用消息队列。您在队列上放置一条消息,工作线程(或进程等)会在您的视图完成后使用队列并执行工作。

Google App Engine 有任务队列 API http://code.google.com/appengine/docs/python/taskqueue/,亚马逊有简单队列服务 http://aws.amazon.com/sqs/

快速搜索并没有找到任何看起来像公认标准的 django 插件。

模拟该功能的一种快速而肮脏的方法是将“消息”放在数据库表中,并让 cron 作业定期检查表以执行工作。

【讨论】:

  • +1 比(希望)轻量级 IPC 消息更有效的想法。
【解决方案4】:

Django 的 HttpResponse 对象在其构造函数中接受一个迭代器:

http://docs.djangoproject.com/en/dev/ref/request-response/#passing-iterators

所以你可以这样做:

def myiter():
    yield "my content"
    enqueue_some_task()
    return

def myview(request):
    return HttpResponse(myiter())

迭代器的正常使用是发送大数据而不将其全部读入内存。例如,从文件中读取块并适当地产生。我从来没有以这种方式使用过它,但它似乎应该可以工作。

【讨论】:

  • 不幸的是,这将使页面在完全加载后似乎仍在客户端加载,因为服务器在产生最终结果之前不会关闭连接。
【解决方案5】:

我最喜欢的解决方案:一个处理后台任务的单独进程,通常是索引和发送通知邮件等。然后,在视图呈现期间,您将一个事件发送到事件处理系统(我不知道 Django有一个内置的,但无论如何你总是需要一个,所以你应该有一个)然后偶数系统将一条消息放入一个消息队列中(除非你有多台机器或多个后台进程,否则这很容易编写)来完成任务问题。

【讨论】:

    【解决方案6】:

    在渲染到响应中,您传递要显示的 html 页面。其他页面需要发送一个帖子(通过 Javascript 或其他方式),以触发您视图中的正确功能,然后该视图调用正确的下一页来显示。

    【讨论】:

    • 是的,可以,但我想知道是否有办法仅在服务器端进行
    • 我不确定这是否真的可能:/
    • 那绝对不能在服务器端完成。服务器不知道客户端在做什么,所以它永远不会知道页面已经完成渲染。当然,一个简单的帖子就可以解决这个问题。
    【解决方案7】:

    也许我不明白你的问题。但为什么不做一些简单的事情:

    try:
        return render_to_response()
    finally:
        do_what_needs_to_be_done()
    

    【讨论】:

    • 一旦返回,视图就会被渲染,对吧?不管最后部分发生了什么?如果是这样,这正是我所需要的!
    • 它似乎不起作用。在 finally 中的代码运行时渲染被暂停。
    • 当有 finally 子句时,函数的返回仅发生在 finally 中的代码执行之后,因此这不会按预期工作。
    猜你喜欢
    • 2020-07-07
    • 2021-07-28
    • 2020-08-17
    • 2021-03-05
    • 1970-01-01
    • 2020-09-16
    • 1970-01-01
    • 2017-09-20
    • 1970-01-01
    相关资源
    最近更新 更多