Django:获取绝对URL而无需访问请求对象

时间:2010-11-10 23:56:28

标签: python django django-signals django-settings

我有一个类似下面的模型。创建实例时,我想向感兴趣的一方发送电子邮件:

class TrainStop(models.Model):
    name = models.CharField(max_length=32)
    notify_email = models.EmailField(null=True, blank=True)

def new_stop_created(sender, instance, created, *args, **kwargs):

    # Only for new stops
    if not created or instance.id is None: return

    # Send the status link
    if instance.notify_email:
        send_mail(
            subject='Stop submitted: %s' % instance.name,
            message='Check status: %s' % reverse('stop_status', kwargs={'status_id':str(instance.id),}),
            from_email='admin@example.com',
            recipient_list=[instance.notify_email,]
        )
signals.post_save.connect(new_stop_created, sender=TrainStop)

但是,reverse调用仅返回URL的路径部分。示例:/stops/9/status/。我需要一个完整的网址,例如http://example.com/stops/9/status/。我如何检索当前网站的主机名和端口(对于不使用端口80的测试实例)?

我最初的想法是通过settings.py中的变量使其可用,然后我可以根据需要访问它。但是,如果有人可能会提出更强有力的建议。

2 个答案:

答案 0 :(得分:4)

获取当前网站的对象网站:

  

如果您无权访问请求对象,则可以使用   Site模型管理器的get_current()方法。那你应该   确保您的设置文件包含SITE_ID设置。这个   示例等同于前一个:

from django.contrib.sites.models import Site

def my_function_without_request():
    current_site = Site.objects.get_current()
    if current_site.domain == 'foo.com':
        # Do something
        pass
    else:
        # Do something else.
        pass

更多信息:http://docs.djangoproject.com/en/dev/ref/contrib/sites/

答案 1 :(得分:4)

正如yedpodtrzitko所提到的那样,有网站框架,但正如你所提到的,这是一个非常多的手动设置。

在settings.py中需要设置一个设置,但它只比设置网站的手动略少。 (它可以处理多个域,就像站点和SITE_ID设置一样)。

replacing get_absolute_url有一个想法,这会使这样的事情更容易,但我认为它的实现遇到了同样的问题(如何获得域名,方案[http vs https]等)。

我一直在研究中间件的想法,该中间件检查传入的请求,并根据HTTP HOST头的值的频率构建某种“最可能的域”设置。或者也许它可以单独为每个请求设置此设置,因此您始终可以使用当前域。我还没有认真研究它,但这是一个想法。