我正在尝试做一些看似相对简单的事情,但我完全被难倒了。我有一个模型,并且我想在第一次创建实例时发送电子邮件。我可以用这个很容易地做到这一点:
@receiver(models.signals.post_save, sender=MyModel)
def execute_after_save(sender, instance, created, *args, **kwargs):
if created:
send_mail(mail_type='MyModel_created', instance=instance)
然而,问题是我需要在电子邮件中将链接发送到管理面板中模型的更改视图。我一直在使用这样的代码(在其他情况下)来构造上面提到的send_mail()函数中的链接:
mymodel_admin_url = request.build_absolute_uri(reverse('admin:mymodels_mymodel_change', args=(instance.id,)))
但是你会注意到这依赖于一个请求对象,它不是通过post_save信号传递的,甚至也不是save方法。在这种情况下,获得我需要的链接的最佳方法是什么?
重建和覆盖所有内容(即save方法,base_save方法,post_save信号等)以传递请求似乎是一场噩梦。但是,我无法使用站点框架获取我需要的链接(有时我在子域上使用该站点,或者例如在使用manage.py runserver进行测试时,并且调用站点框架不会构建正确的链接)。
答案 0 :(得分:2)
有没有办法使用网站框架来返回真正的绝对网址,例如request.build_absolute_uri()
呢?
问题是,通常,不是真正的绝对URL。 Django可以在没有Web服务器的情况下正常工作,生成电子邮件,保存模型(并触发保存后信号)等。如果有Web服务器,Django无法知道它所服务的域名,这就是为什么你需要一个请求对象以及你需要ALLOWED_HOSTS
等设置的原因
您处理此问题的一般方法是明确告知Django它所服务的网站。例如,对于每个分发,您将拥有不同的设置文件,并且如果您使用SITE_ID
框架,则每个文件都将指示应使用的域名(通过sites
设置;或者否则你可以用你自己的设置明确说明。对不同的服务器使用不同的设置文件是常见的做法。
现在,在您的特定情况下,听起来似乎是在Web请求中(通过管理员?)触发了保存,因此如果您可以获得该请求,则可以使用其域名来构建您的链接。 Django没有包含任何方式来获取该请求,除非将其作为参数传递。但是,你不是第一个想要这个的人,所以如果你搜索“Django全局请求”,你可以看到其他人如何处理这个问题。例如,This article提出了一些想法,this app旨在“在需要时”访问Django的HTTPRequest
对象,而不是明确地将其传递到代码路径中。“ / p>