我響應,因爲你的「我想知道是否有另一種解決方案」的評論的。有。我有它在網站上運行...多個SQLite數據庫與一個應用程序。你也提到了數據庫路由器問題,我也在努力。
首先,把任何地方router.py
文件,該文件包含以下內容:
class Router(object):
appname = ''
def db_for_read(self, model, **hints):
"""
Attempts to read self.appname models go to model.db.
"""
if model._meta.app_label == self.appname:
return model.db
return None
def db_for_write(self, model, **hints):
"""
Attempts to write self.appname models go to model.db.
"""
if model._meta.app_label == self.appname:
return model.db
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in the self.appname app is involved.
"""
if obj1._meta.app_label == self.appname or \
obj2._meta.app_label == self.appname:
return True
return None
# This is possibly the new way, for beyond 1.8.
'''
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Make sure the self.appname app only appears in the self.appname
database.
"""
if app_label == self.appname:
return db == self.appname
return None
'''
# Contrary to Djano docs this one works with 1.8, not the one above.
def allow_migrate(self, db, model):
"""
Make sure the self.appname app only appears in the self.appname
database.
"""
if db == self.appname:
return model._meta.app_label == self.appname
elif model._meta.app_label == self.appname:
return False
return None
我只使用Django 1.8測試這一點;正如你使用1.9,根據文檔,至少必須使用其他allow_migrate
。
特別要注意的是:(1)沒有帶有屬性的Router()的squirously基類,這意味着Python type
函數可以很容易地用來克隆它; (2)很明顯,當前模型實例可以通過外部命名空間在Router()
內部訪問。
所以,現在,在你的models.py
,這樣做:
from django.db import models
import os
appname = os.path.dirname(__file__).split('/')[-1]
from dirwhereyouputtherouter.router import Router
router = type(appname, (Router,), dict(appname=appname))
class Book(models.Model):
# This is the default, for use when there is only one db per app.
db = appname
# the various fields here, etc.
做到這一點對每個模型。然後Router()
當遇到任何查詢將return model.db
。我在這裏選擇,在我的方案中,讓應用程序的默認Django方案從其目錄的名稱中獲取它的名稱。
現在,在settings.py
中,您需要DATABASE_ROUTERS = [ 'appdir.models.router', ]
。這指示通過使用type()
函數在models.py
中初始化的router
查詢。特別要注意的是,我沒有在DATABASE_ROUTERS
列出default
數據庫。我確實有一個,它在DATABASES
設置中列出,其中default
爲關鍵。當您進行初始遷移時,各種Django應用程序表最終將在default
數據庫中結束,當然,因爲Router()
將退出。
因此,在您的視圖中,您將從Book.db = x
開始,其中視圖簽名爲myview(request, x, someothername):
。有一個機會,你可能想要在finally
塊中使用try: finally:
來填充整個視圖體,你可以將數據庫的選擇返回到某個默認值。
我必須承認,當涉及到遷移時,軟膏中可能會有蒼蠅。我討厭那些,在我的情況下,我會在我更新它們的時候寫下我的小SQLite數據庫的全部內容,這經常是這樣。所以,不用擔心保存數據,只要需要進行更改,我就會將它們和Migrations文件夾丟棄。但是如果你的情況不同,你可能不得不努力與migrate
和makemigrations
命令。我的每個數據庫都具有相同的模式,由模型定義。所以我實際上首先創建了一個空白數據庫,臨時在DATABASES
設置中輸入一個與應用程序名稱相同的條目。我用它創建SQLite數據庫文件的一個副本,然後只需複製它並在我想添加新數據庫時將其重命名(將新數據庫的詳細信息添加到DATABASES
並刪除以appname作爲關鍵字的臨時條目)。或者,您可能希望保留並善用其DATABASES
中的密鑰是應用程序名稱的數據庫。
但遺憾的是,我們沒有完成。我不得不修復admin.py
。在admin.py
class BookAdmin(admin.ModelAdmin):
中創建之後,按照通常的方式,您將無法在管理員中找到您的兩個數據庫。所以我admin.py
樣子:
from django.contrib import admin
from django.conf import settings
import os
class BookAdmin(admin.ModelAdmin):
list_display = ...
list_filter = ...
etc.
from models import Book
appname = os.path.dirname(__file__).split('/')[-1]
dbkeys = settings.DATABASES.keys()
while 'default' in dbkeys: dbkeys.remove('default')
dbkeys = [ k for k in dbkeys if os.path.dirname(settings.DATABASES[k]['NAME']).split(os.sep)[-1] == appname ]
for dbname in dbkeys:
if dbname == dbkeys[0]:
class Book_(Book):
class Meta:
proxy = True
verbose_name = Book.__name__ + '_' + ''.join('_' + x.capitalize() or '_' for x in dbname.split('_'))
verbose_name_plural = Book.__name__ + 's_'+ ''.join('_' + x.capitalize() or '_' for x in dbname.split('_'))
db_table = appname + '_book'
Book_.db = dbname
Book_.__name__ = Book.__name__ + '_' + appname.capitalize() + '_' + ''.join('_' + x.capitalize() or '_' for x in dbname.split('_'))
admin.site.register(Book_, BookAdmin)
elif dbname == dbkeys[1]:
class Book__(Book):
class Meta:
proxy = True
verbose_name = Book.__name__ + '_' + ''.join('_' + x.capitalize() or '_' for x in dbname.split('_'))
verbose_name_plural = Book.__name__ + 's_'+ ''.join('_' + x.capitalize() or '_' for x in dbname.split('_'))
db_table = appname + '_book'
Book__.db = dbname
Book__.__name__ = Book.__name__ + '_' + appname.capitalize() + '_' + ''.join('_' + x.capitalize() or '_' for x in dbname.split('_'))
admin.site.register(Book__, BookAdmin)
這工作,因爲我把數據庫文件在該應用程序的文件夾中的每個應用程序。對不起,這一切都有點棘手。我有很好的理由想要這個能力。另請參閱我未回答的有關子分類模型的問題,以便使用admin.site.register
,here進行註冊。
而且你必須有單獨的數據庫,因爲......?您是否考慮過使用URL路徑段作爲標識符的替代方法,並將該標識符用作外鍵來過濾數據? – Brandon
,因爲它們裏面的表格將具有相同的結構,但具有不同的數據,現在的URL不是一個大問題。問題在於「1個模型,1個視圖和1個多個數據庫的表單」,以避免大量的重複。 – rrawat
如果數據不同,它會有什麼不同?它都是通過外鍵分隔的。外鍵方法將您的複雜度降低了一個數量級。 – Brandon