Django:渲染视图后如何更新模型?
Posted
技术标签:
【中文标题】Django:渲染视图后如何更新模型?【英文标题】:Django: How do I update a model after a view has been rendered? 【发布时间】:2011-09-05 20:14:35 【问题描述】:我有一个显示模型列表的视图。某些模型的某些属性需要在视图呈现后更新:即,用户应该在第一次访问时看到原始的、未更改的值,而在连续访问时(或在页面重新加载时)看到更新后的值.
我认为我可以使用基于类的通用视图来实现这一点。 official documentation 暗示“在调用通用视图之前或之后做一些额外的工作”(强调我的),但所有给出的示例都会在模型显示之前影响模型。
我查看了信号,但无济于事。
生成一个异步任务是一种选择,但是,由于我需要做的就是更新几个模型中的一个字段(可能有一个或没有)并保存它们,这对于手头的任务来说似乎有点矫枉过正。
可以使用 ajax 请求来触发更新,或者使用自定义模板标签来显示相关字段并在之后更新它们。我不喜欢两者,因为它们将应用程序逻辑移动到视图层。 ajax 技术还增加了第二个请求的开销。
然而,我似乎别无选择,不是吗?是否有更实用的技术来插入通用视图或请求并在模板渲染后执行额外的逻辑?
【问题讨论】:
【参考方案1】:从视图或函数中获取返回值,进行一些处理,然后将其踢入堆栈。
def foo(*args):
ret = bar(*args)
do_something()
return ret
【讨论】:
我试过了,但它不起作用。当原始视图返回时,模板还没有被解析,所以修改显示在第一个可视化中。【参考方案2】:您能否获取该对象的两份副本,修改并保存一份,同时将另一份(未修改和过时的)传递给视图?
我还没有使用过基于类的通用视图,所以我不能给你一个具体的例子。
【讨论】:
应该可以,但它意味着将一个(可能很长的)列表传递给模板。我更喜欢开销更少的解决方案。【参考方案3】:这里不需要任何聪明的东西。渲染模板不一定是视图的结束 - 只有当您实际 return 将其作为响应时才会出现。它们不必在同一步骤中。
所以:
def my_view(request, params):
#...do something...
response = render_to_response('my_template.html', 'foo': bar)
# ...do something after rendering...
return response
现在,如果您需要在很多视图中执行此操作,您可能希望在装饰器中执行此操作:
def my_decorator(view):
def my_func(request, params):
response = view(request, params)
#...do something after rendering...
return response
return my_func
现在您可以使用@my_decorator
装饰您的视图,并且该操作将在渲染后执行。
...或者,我刚刚想到,如果您想在 every 视图中执行此操作,您可以在中间件中执行此操作(只需定义 process-response
方法)。
评论后编辑 基于类的通用视图使用新的 TemplateResponse 类。您可以使用post-render callback 添加在模板实际呈现后发生的任务。
【讨论】:
虽然这应该适用于您手动执行视图工作的情况,但如果您将可视化委托给通用视图(我只尝试使用基于类的通用视图,但是基于函数的通用视图无论如何都被弃用了),因为从视图返回时模板还没有被解析,所以它会看到更新的模型。render_to_response
在 django >2.0 中只是render
【参考方案4】:
Django 还附带了一个built-in signalrequest_finished
,它在 django 处理完请求后发送。
【讨论】:
【参考方案5】:如果您的项目已经使用 celery,您可以创建一个任务来更新模型并 并调用
your_task.delay()
您可以使用倒计时参数来指定启动任务之前经过的时间。
如果您不使用芹菜,那么您将来会使用 :)
【讨论】:
以上是关于Django:渲染视图后如何更新模型?的主要内容,如果未能解决你的问题,请参考以下文章
如何根据 django 模板中的不同提交按钮在更新视图中自定义成功 url?
如何访问 django settings.py 中的模型或视图属性?