django - django SITE_ID 通过查询
问题描述
我有一个 Django 应用程序。我正在添加第二个站点。
所以现在我需要正确设置 SITE_ID。这很容易,除了因为它是 Site 表中的主键 id,这意味着该值取决于添加(并最终删除)站点的顺序。这很脆弱,甚至没有讨论如果开发人员在该表中做了任何临时工作,他们将如何对其进行排序。通过查询设置它要好得多。
SITE_ID = Site.objects.get(name='my_site_name').id
但是设置 的settings_myapp.py
文件WSGI_APPLICATION
几乎是唯一可能知道我正在运行哪个应用程序的文件。我可以尝试settings
在该站点特定的设置文件中进行修改,但此时导入设置会导致SECRET_KEY
尚未定义的错误。
有没有一种强大的方法来做到这一点?
解决方案
这是我如何解决我在问题中陈述的问题的总结。当我问这个问题时,我并不知道,实际上有几个方面需要不同的方法。
一点中间件对已部署的实例(即,不是开发实例)有很大帮助。 该解决方案提供了 django 3.1 就绪的代码片段,因为过去存在的解决方案不再与现代 django 兼容。
对于开发人员,我将此添加到我的settings.py
:
DEFAULT_SITE_ID = os.getenv('DEFAULT_SITE_ID')
所以上面的代码片段变成了这样:
class DynamicSiteDomainMiddleware:
default_site_id = None
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
self.default_site_id = settings.DEFAULT_SITE_ID
if self.default_site_id is not None:
current_site = Site.objects.get(id=self.default_site_id)
def __call__(self, request):
if self.default_site_id is None:
try:
current_site = Site.objects.get(domain=request.get_host())
except Site.DoesNotExist:
current_site = Site.objects.get(id=settings.DEFAULT_SITE_ID)
else:
current_site = Site.objects.get(id=self.default_site_id)
request.current_site = current_site
settings.SITE_ID = current_site.id
response = self.get_response(request)
return response
换句话说,如果开发人员已设置DEFAULT_SITE_ID
(例如,在调用时在命令行上manage.py
)使用该值。否则,我们会根据请求查看 SNI。
这留下了一个未解之谜:该怎么办urlpatterns
?我有两个站点(很快三个),它们的 URL 方案略有不同。但urls.py
总的来说,在这个巧妙的中间件解决方案下,站点信息尚不可用,因为 urlpatterns (自然且必然)在任何请求发生之前设置。
对我来说最好闻的方法设置了一个环境变量,以便settings.py
可以ROOT_URLCONF
针对其特定情况进行设置。
ROOT_URLCONF = os.getenv('ROOT_URLCONF', 'transport_nantes.urls_tn')
一个明显的缺点是我们最终陷入了两种不兼容的设置站点数据的机制:DEFAULT_SITE_ID
+ SNI 和ROOT_URLCONF
. 然而,这并不像看起来那么糟糕,因为这是问题的两个独立方面:我是什么站点以及我想要拥有的 URL 方案。这需要对生产和暂存部署代码进行非常小的更改以设置适当的环境变量。
最后,在每个url_XYZ.py
文件中,我为该版本网站的基本模板设置了一个变量。(问题在于链接不同。如果只是更改徽标,那会更容易。)我将 dict 中的值传递给包含的 url 文件,因此我可以在呈现视图时使用该知识,即使视图功能通常在多个站点和 URL 方案之间共享。
那么为什么不也为 设置一个环境变量SITE_ID
呢?这又回到了最初的问题:站点 id 是脆弱的,它是站点表中的主键。可以合理地想象一些维护会使站点表保持不变,除了更改的主键(例如,无意删除然后重新创建记录)。因此,按名称查找值更加健壮。
另一方面,该ROOT_URLCONF
变量的优点是它不绑定到站点表。例如,站点 X 有一个特定的 URL 方案,无论 X 是在生产、暂存或测试中运行,都是如此,所有这些都有不同的 FQDN。
推荐阅读
- javascript - React 或 Javascript 的扩展子类如何工作?
- python - Matplotlib 透明面设置
- java - java中词法字符串比较背后的逻辑是什么?
- javascript - 为什么在我的 Rails 应用程序中未定义预编译的 vanilla JS 脚本中的 const,但在我删除 const 关键字时有效
- c# - 二维动态数组/列表语法问题
- java - BiqQuery 在 Apache Beam 中插入重试策略
- c++ - 链表删除节点不起作用,到达该部分时程序崩溃
- javascript - 如何通过编写测试脚本在邮递员中测试 API 的速率限制?
- eclipse - 泛型:类型参数不在其范围内
- java - Timer 任务中的 Run 方法正在执行两次