如何在Django中获取URL(带有协议和域)(没有请求)?

时间:2016-01-25 09:27:02

标签: django url cron

我想在cron工作中发送邮件。邮件应该包含 我的申请的链接。

在cron工作中,我没有请求对象,也无法使用request.build_absolute_uri()。

AFAIK网站框架可以在这里提供帮助。但是没有给我协议(http vs https)?

我的应用程序是可重用的,有时会在http上托管,有时在https网站上托管。

更新

我搜索一个常见的django方式。可以创建自定义设置,但首选django标准的解决方案。

相关问题:https://code.djangoproject.com/ticket/16734

2 个答案:

答案 0 :(得分:20)

TL; DR 没有任何“标准”“Django-ish”方式,但框架推广的DRY原则假定单一配置存储,所以自定义设置似乎是一个很好的方法。

默认情况下,Django可以从单个实例提供任意数量的域,而HTTP请求(更确切地说,它的HTTP_HOST标头)是Django用来确定当前主机的唯一内容。 由于您的cron作业显然不属于HTTP周期,因此您应该将域存储在设置中...

# settings.py
DEFAULT_DOMAIN = 'https://foobar.com'
# or, depending on your configuration:
DEFAULT_DOMAIN = 'https://{}'.format(ALLOWED_HOSTS[0])

...使用微小的上下文处理器,可以更轻松地处理模板:

# yourapp/context_processors.py
from django.conf import settings

def default_domain(request):
    return {'default_domain': settings.DEFAULT_DOMAIN}

...然后在您的电子邮件中使用它:

# yourapp/templates/email/body.html
<a href="{{ default_domain }}{% url 'target' %}">Click here</a>

或者您可以使用sites框架,但如果您正在为单个域提供服务,基于设置的解决方案对我来说似乎更简单,更清晰。

答案 1 :(得分:15)

此任务有专门的标准模块 - Sites Framework。 它添加了Site模型,它描述了特定的站点。此模型包含项目域的字段domain,以及name - 网站的人类可读名称。

您将模型与网站相关联。像这样:

from django.db import models
from django.contrib.sites.models import Site

class Article(models.Model):
    headline = models.CharField(max_length=200)
    # ...
    site = models.ForeignKey(Site, on_delete=models.CASCADE)

当您需要为对象创建网址时,您可以使用以下代码:

   >>> from django.contrib.sites.models import Site
   >>> obj = MyModel.objects.get(id=3)
   >>> obj.get_absolute_url()
   '/mymodel/objects/3/'
   >>> Site.objects.get_current().domain
   'example.com'
   >>> 'https://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url())
   'https://example.com/mymodel/objects/3/'

通过这种方式,您可以在它们之间传播多个域和内容。 即使您只有一个域名,我建议您使用它来实现保持域名设置的良好标准。

安装非常简单:

  1. 'django.contrib.sites'添加到您的INSTALLED_APPS设置。

  2. 定义SITE_ID设置:

     SITE_ID = 1
    
  3. 运行迁移。