在Django中基于服务器名称动态提供静态内容

时间:2011-09-13 23:23:12

标签: python django

我正在Django中编写一个Web应用程序,可以从多个域访问同一个IP地址。我们的想法是,从中访问应用程序的每个域都将获得独特的品牌。

因此,例如,如果有两个域名,reseller.com和oem.com,并且您访问了oem.com,则会转到与reseller.com相同的网站,但使用不同的主题内容(比如说,从/static/oem.com/{files}发送,而不是/static/reseller.com/ {files})。

基本上我的想法是定义一个自定义模板标记,它接收SERVER_NAME作为参数,它将返回内容的位置。

有没有其他选择,或者更简单的选择?

编辑:我应该补充一点,我正在为这个项目使用MongoDB,因此很可能Django的ORM不会用于该项目。

再次编辑:更多澄清;我正在使用nginx。

3 个答案:

答案 0 :(得分:1)

您正在寻找the "sites" framework

答案 1 :(得分:1)

不确定如何在nginx中执行简单的重写规则。除了模板标签(如果你只是交换静态内容,那么我认为模板标签是要走的路),如果网站将完全不同,模板方面,你可以通过编写自定义来处理它模板加载器。

这允许您选择在渲染页面时要使用的模板。如果加载程序无法为您的特定域找到匹配的模板,则此方法具有优雅的失败方式。如果找不到匹配项,它将回退到您的主模板目录。因此,您可以为某些域提供自定义内容,对其他域更为通用。

但是要根据请求标头决定要提供什么服务,您需要通过_thread_locals将请求提供给加载器,我在一些中间件中执行此操作:

#custom.middleware.py
try:
    from threading import local
except ImportError:
    from django.utils._threading_local import local

_thread_locals = local()

def get_current_request():
    return getattr(_thread_locals, 'request', None)

class RequestMiddleware():
    def process_request(self, request):
        _thread_locals.request = request

接下来编写一个模板加载器(更新中间件的路径):

#custom.loaders.py
from os.path import join
from django.conf import settings
from django.template import TemplateDoesNotExist
from path.to.middleware import get_current_request

def load_template_source(template_name, template_dirs=None):
    request = get_current_request()
    host = request.get_host()
    path_to_template_dir = None
    for site in settings.SITE_TEMPLATE_FOLDERS:
        if site[0] == host:
            path_to_template_dir = site[1]
            break

    if path_to_template_dir:
        try:
            filepath = join(path_to_template_dir, template_name)
            file = open(filepath)
            try:
                return (file.read(), filepath)
            finally:
                file.close()
        except IOError:
                pass

    raise TemplateDoesNotExist(template_name)

最后用三件事更新你的设置文件1)添加模板加载器(确保首先列出)2)添加中间件3)然后添加一个新变量SITE_TEMPLATE_FOLDERS,其中包含一个包含域和模板路径的元组元组文件夹:

#settings.py

.....

TEMPLATE_LOADERS = (
    'custom.loaders.load_template_source',
    'django.template.loaders.filesystem.load_template_source',
    'django.template.loaders.app_directories.load_template_source',
)

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'domain.middleware.SessionMiddleware',
    'custom.middleware.RequestMiddleware',
)

SITE_TEMPLATE_FOLDERS = (
    ('mydomain.com', '/path/to/templates'),
    ('myotherdomain.com', '/path/to/other/templates')
)
...

似乎很多,但现在您可以通过设置文件轻松添加新域。

答案 2 :(得分:0)

例如,Apache有mod_rewrite可用于重写URL:

RewriteCond %{HTTP_REFERER} ^www.domain1.com$ [NC]
RewriteRule /static/[^/]+ /static/domain1/$1 [L]
RewriteCond %{HTTP_REFERER} ^www.domain2.com$ [NC]
RewriteRule /static/[^/]+ /static/domain2/$1 [L]
(这是未经测试的)

其他服务器也具有类似的功能。

只需确保您的django应用程序发出与站点无关且可以正确重写的静态URL。