2

我是 Django 和 python 的新手,所以请多多包涵。我想创建一个非常简单的 SaaS 应用程序来开始使用 Django 和 python。我的设计规定所有域都将在相同的代码库上运行。每个网站之间唯一不同的是数据库连接详细信息。(IE 每个域都有自己的数据库。所有数据库都包含相同的架构)

我将如何使用 Django 来解决这个问题?我已经看过 Sites 框架,但我不确定这就是我想要的。本质上,我想要么

A) 让 Django 在页面加载时从 MASTER 数据库中查找数据库连接详细信息,然后在连接到站点数据库时使用这些详细信息

B)每个站点都有一个settings.py,并让django在运行时包含正确的文件(IE settings_domain.py)

C)让索引 WSGI 包含基于访问域的适当设置文件(这似乎可以工作,但我确信我错过了这个实现的潜在缺陷)

D)我没有想到的其他一些实现......

我是否使这比需要的更复杂?我怎样才能轻松地将这个功能实现到一个新的 django 项目中?

4

2 回答 2

3

嗯,有一个有趣的项目:https ://bitbucket.org/uysrc/django-dynamicsites 。它试图让您拥有完全独特的站点,所有站点都运行在同一个项目中。但是,目前,我认为它不会对您有太大帮助,因为您需要对设置进行比它提供的更多的自定义。

实际上我只是自己做的,最初尝试使用 django-dynamicsites,但发现它有点过于敏感,不太适合我的项目。结果,我最终采取了一些不同的方法。

我的项目有一个“站点”模块,其中每个唯一站点都有一个模块。每个模块都有自己的 settings.py 和 urls.py 和模板目录。例如:

sites
    - __init__.py
    - site1
        - __init__.py
        - settings.py
        - urls.py
        - templates
            - base.html
    - site 2
        - __init__.py
        - settings.py
        - urls.py
        - templates
            - base.html

每个 settings.py 大致如下:

from myproject.settings import *

SITE_ID = 1
URL_CONF = 'sites.site1.urls'

SITE_ROOT = os.path.dirname(__file__)
TEMPLATE_DIRS = (
    os.path.join(SITE_ROOT, 'templates')
)

CACHE_MIDDLEWARE_KEY_PREFIX = 'site1'

因此,它的作用是导入您的项目设置文件,然后覆盖站点独有的设置。然后,您所要做的就是确保您使用的任何服务器都加载特定站点的 settings.py 而不是主项目的 settings.py。我正在使用 nginx+Gunicorn 的组合,所以这里的配置大致是这样的:

site1.conf (nginx)

upstream site1 {
    server 127.0.0.1:8001 fail_timeout=0;
}

server {
    listen 80;
    server_name site1.domain.com;

    root /path/to/project/root;

    location / {
        try_files $uri @proxy;
    }

    location @proxy {
        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_connect_timeout 10;
        proxy_read_timeout 30;
        proxy_pass http://site1;
        proxy_redirect off;
    }

}

我使用主管来管理 Gunicorn 服务器,所以这是我的配置:

site1.conf(主管)

[program:site1]
command=/path/to/virtualenv/bin/python manage.py run_gunicorn --settings=sites.site1.settings
directory=/path/to/project/root
user=www-data
autostart=true
autorestart=true
redirect_stderr=True

重要的部分是没有花哨的 Django 中间件或此类检查特定主机并相应地以这种方式或那种方式进行。您在 uwsgi、Gunicorn 等上为每个指向正确的 settings.py 文件启动一个 Django 实例,并且您的网络服务器将每个子域的请求代理到匹配的上游连接。

于 2012-05-11T20:40:03.373 回答
0

最好的方法是在您的网络服务器上进行重写/代理,无论是 apache 还是 nginx。在 apache 中,您可以使用类似这样的内容设置主机文件以捕获所有域。django 将获得一个 URL,然后它可以确定它是哪个域。

<VirtualHost *:80>
     ServerName domain.com
     ServerAlias *
     DocumentRoot /var/www/domain.com/DjangoProj/public

     Alias /media/ /var/www/domain.com/DjangoProj/misc/media/
     Alias /static/ /var/www/domain.com/DjangoProj/misc/static/

     <Directory /var/www/domain.com/DjangoProj/public>
         Order deny,allow
         Allow from all
     </Directory>

     WSGIScriptAlias / /var/www/domain.com/DjangoProj/app/wsgi.py

     <Directory /var/www/domain.com/DjangoProj/app>
     <Files wsgi.py>
     Order deny,allow
     Allow from all
     </Files>
     </Directory>

     <IfModule mod_rewrite.c>
          RewriteEngine on
          RewriteCond %{HTTP_HOST} ^(.*) [NC] # Catch domain
          RewriteCond %{REQUEST_URI} !userdomain [NC] # Don't rewrite if we already have it
          RewriteRule ^(.*)$ /userdomain/%1$1 [PT,L] # Pass in PT to give the URL back to mod_python!
     </IfModule>

     ErrorLog /var/www/domain.com/logs/error.log
     CustomLog /var/www/domain.com/logs/access.log combined
</VirtualHost>
于 2012-05-11T20:39:07.127 回答