在将实例保存到数据库之前/之后是否触发了Django post_save?

Kar*_*bhu 7 python django post save

我有一个使用Django的网站.每个帖子都是一个名为Article的对象.我想在保存后检索帖子的HTML,所以我编写了以下post_save钩子:

@receiver(models.signals.post_save, sender=Article)
def _send_article_mentions(sender, instance, **kwargs):
    import requests
    from django.contrib.sites.models import Site
    from urlparse import urljoin
    from ParallelTransport.settings import ARTICLES_URL
    SITE_URL = 'http://'+Site.objects.get_current().domain
    article_url = urljoin( SITE_URL, instance.get_absolute_url() )
    import time
    time.sleep(20)
    r = requests.get(article_url)
    error_file = open(ARTICLES_URL+'/'+'error.txt','w')
    error_file.write('file started1\n')

    m = r.status_code
    error_file.write(str(m))
    error_file.close()
Run Code Online (Sandbox Code Playgroud)

它基本上等待20秒(作为测试添加)然后尝试使用其URL检索帖子的HTML,并将请求状态代码写入文件以进行调试.

问题是我在第一次保存时总是获得status = 404,它在第二次和后续保存时都有效.我认为Django的工作方式是:

  1. 使用save()将实例保存到数据库.此时帖子会获得一个URL
  2. 发送post_save信号

但后来我应该能够在post_save中检索HTML.我对post_save的理解不正确吗?

补充说明:

  1. 将此代码放在save()方法中不起作用.也不应该.该帖子在save()方法的末尾添加到数据库中,因此在save()结束之前不应该有任何URL.
  2. 这是在生产站点上,而不是在开发服务器上.
  3. 我想使用HTML中的链接发送'pingbacks'或实际webmention.但我的所有pingback都被拒绝了,因为帖子还没有URL.这是最不起作用的最低代码.

Bru*_*uce 4

虽然这是一个完全错误的方法(*),但问题可能出在数据库事务中。当前线程保存文章,但在此未提交的事务中,您尝试通过另一个线程(通过 Web 服务器)获取这些数据。在这种情况下,这种行为是完全正确的。您需要在通过另一个线程检索之前提交,或者通过其他方式获取 HTML。

(*) 应该在后台异步完成(Celery 或其他更轻量级的异步队列应用程序),或者如果您想获取 HTML,您可以直接调用视图(根据您的视图,您可能必须伪造请求;如果太复杂,您可以创建一个辅助函数来挑选最少的代码来呈现模板)。如果您只需要在保存某些内容后调用第 3 方 API,那么您希望异步执行。如果您不这样做,“save() 代码”的成功将取决于您的连接或第 3 方服务的可用性,并且您将需要在您不会处理交易的地方处理交易;)

  • 在事务数据库中,如果执行插入/更新查询,修改的数据不会真正保存,它们是临时的。这与打开 txt 文件、进行更改但不保存文件的原理相同。您会在屏幕(当前线程)上看到更改,但是当其他人打开同一文件(另一个 Web 服务器线程)时,会出现旧内容。文件打开多长时间(您的睡眠时间)并不重要,您必须执行 Ctrl+S(提交),然后其他人才能看到。 (2认同)