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

发布于 2024-10-01 20:35:58 字数 1144 浏览 6 评论 0原文

我有一个像下面这样的模型。创建实例后,我想向感兴趣的各方发送一封电子邮件:

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='[email protected]',
            recipient_list=[instance.notify_email,]
        )
signals.post_save.connect(new_stop_created, sender=TrainStop)

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

我最初的想法是通过 settings.py 中的变量使其可用,然后我可以根据需要访问该变量。然而,我认为有人可能有更强有力的建议。

I have a model like the one below. When an instance is created, I want to send out an e-mail to an interested party:

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='[email protected]',
            recipient_list=[instance.notify_email,]
        )
signals.post_save.connect(new_stop_created, sender=TrainStop)

However, the reverse call only returns the path portion of the URL. Example: /stops/9/status/. I need a complete URL like http://example.com/stops/9/status/. How would I go about retrieving the hostname and port (for test instances that do not use port 80) of the current website?

My initial thought was to make this available via a variable in settings.py that I could then access as needed. However, thought someone might have a more robust suggestion.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七颜 2024-10-08 20:35:58

正如 yedpodtrzitko 提到的,有网站框架,但是,正如您提到的,它很大程度上是一个手动设置。

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

有一个替换 get_absolute_url 的想法,这将使这样的事情变得更容易,尽管我认为它的实现会受到影响来自同样的问题(如何获取域名、方案[http vs https]等)。

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

There's the sites framework, as yedpodtrzitko mentioned, but, as you mentioned, it's very much a manual setup.

There's requiring a setting in settings.py, but it's only slightly less manual than setting up sites. (It can handle multiple domains, just as well as sites and the SITE_ID setting can).

There's an idea for replacing get_absolute_url, that would make stuff like this easier, though I think its implementation suffers from the same problem (how to get the domain, scheme [http vs https], etc).

I've been toying with the idea of a middleware that examines incoming requests and constructs a "most likely domain" setting of some sort based on the frequency of the HTTP HOST header's value. Or perhaps it could set this setting on each request individually, so you could always have the current domain to work with. I haven't gotten to the point of seriously looking into it, but it's a thought.

日久见人心 2024-10-08 20:35:58

为了获取当前站点,有对象 Site:

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

from django.contrib.sites.models import Site

def my_function_without_request():
    current_site = Site.objects.get_current()
    如果 current_site.domain == 'foo.com':
        # 做点什么
        经过
    别的:
        # 做点别的事。
        经过

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

For getting current site there's object Site:

If you don’t have access to the request object, you can use the
get_current() method of the Site model’s manager. You should then
ensure that your settings file does contain the SITE_ID setting. This
example is equivalent to the previous one:

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

More info: http://docs.djangoproject.com/en/dev/ref/contrib/sites/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文