使用数据库路由器在应用程序 Django 之间共享(mysql)数据库
Posted
技术标签:
【中文标题】使用数据库路由器在应用程序 Django 之间共享(mysql)数据库【英文标题】:Sharing (mysql) database between apps Django with Database routers 【发布时间】:2014-03-28 16:33:10 【问题描述】:我创建了一个 django 项目,然后创建了两个应用,app1 和 app2。我希望两个应用程序共享一个 mysql 数据库('nameofDB' 到 mysql,'mydb' 到 django)。我在 settings.py 中将数据库添加到 DATABASES,并为每个应用程序创建了一个 dbrouter 文件,并将每个路由器添加到 DATABASE_ROUTERS。同样在 settings.py 中将每个应用程序添加到 INSTALLED_APPS。
我的问题是当我尝试制作时
python manage.py syncdb --database=mydb
因为它不会同步两个应用程序(仅 app1)。它说:
Creating tables ...
Creating table app1_model1
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
这里是我的 settings.py:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app1',
'app2',
)
DATABASES =
'default':
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
,
'mydb':
'ENGINE': 'django.db.backends.mysql',
'NAME': 'nameofDB',
'USER':'username',
'PASSWORD':'password',
DATABASE_ROUTERS = ['app1.dbRouter.App1DBRouter', 'app2.dbRouter.App2DBRouter']
这是我的模型:
app1/models.py:
class Model1(models.Model):
name = models.CharField(max_length=100)
app2/models.py:
class Model2(models.Model):
name = models.CharField(max_length=100)
这是我的数据库路由器
app1/dbRouter.py
class App1DBRouter(object):
def db_for_read(self,model, **hints):
if model._meta.app_label == 'app1':
return 'mydb'
return None
def db_for_write(self,model, **hints):
if model._meta.app_label == 'app1':
return 'mydb'
return None
def allow_relation(self,obj1, obj2, **hints):
if obj1._meta.app_label == 'app1' and \
obj2._meta.app_label == 'app1':
return True
return None
def allow_syncdb(self,db, model):
if db == 'mydb':
return model._meta.app_label == 'app1'
elif model._meta.app_label == 'app1':
return False
return None
app2/dbRouter.py
class App2DBRouter(object):
def db_for_read(self,model, **hints):
if model._meta.app_label == 'app2':
return 'mydb'
return None
def db_for_write(self,model, **hints):
if model._meta.app_label == 'app2':
return 'mydb'
return None
def allow_relation(self,obj1, obj2, **hints):
if obj1._meta.app_label == 'app2' and \
obj2._meta.app_label == 'app2':
return True
return None
def allow_syncdb(self,db, model):
if db == 'mydb':
return model._meta.app_label == 'app2'
elif model._meta.app_label == 'app2':
return False
return None
它有什么问题?我该怎么办?提前致谢! :)
【问题讨论】:
allow_syncdb() 方法应在 db==default 和 model._meta.app_label==myapp 的条件下返回 False。尝试阅读***.com/questions/7360774/…的答案 你确定这里需要两个数据库吗?在应用程序之间共享数据库是正常的普通行为,不需要路由器。 【参考方案1】:可能 app2_model2 是之前创建的,检查一下!
你可以这样做:
settings.py
DATABASE_APPS_MAPPING = 'app1': 'mydb', 'app2': 'mydb'
DATABASE_ROUTERS = ['path.router.DatabaseAppsRouter']
router.py
from django.conf import settings
class DatabaseAppsRouter(object):
"""
A router to control all database operations on models for different
databases.
In case an app is not set in settings.DATABASE_APPS_MAPPING, the router
will fallback to the `default` database.
Settings example:
DATABASE_APPS_MAPPING = 'app1': 'db1', 'app2': 'db2'
"""
def db_for_read(self, model, **hints):
"""Point all read operations to the specific database."""
if settings.DATABASE_APPS_MAPPING.has_key(model._meta.app_label):
return settings.DATABASE_APPS_MAPPING[model._meta.app_label]
return None
def db_for_write(self, model, **hints):
"""Point all write operations to the specific database."""
if settings.DATABASE_APPS_MAPPING.has_key(model._meta.app_label):
return settings.DATABASE_APPS_MAPPING[model._meta.app_label]
return None
def allow_relation(self, obj1, obj2, **hints):
"""Allow any relation between apps that use the same database."""
db_obj1 = settings.DATABASE_APPS_MAPPING.get(obj1._meta.app_label)
db_obj2 = settings.DATABASE_APPS_MAPPING.get(obj2._meta.app_label)
if db_obj1 and db_obj2:
if db_obj1 == db_obj2:
return True
else:
return False
return None
def allow_syncdb(self, db, model):
"""Make sure that apps only appear in the related database."""
if db in settings.DATABASE_APPS_MAPPING.values():
return settings.DATABASE_APPS_MAPPING.get(model._meta.app_label) == db
elif settings.DATABASE_APPS_MAPPING.has_key(model._meta.app_label):
return False
return None
【讨论】:
【参考方案2】:我同意丹尼尔·罗斯曼的观点。当您有两个或多个应用程序使用相同的数据库时,使用一个路由器可能会很好。一般来说,每个非默认数据库可能有一个路由器?
但如果你真的需要两个路由器,这里是一个解决方案。
只要 allow_syncdb 返回 None,Django 根 db 路由器就会尝试 DATABASE_ROUTERS 中的所有路由器。因此 App1DBRouter.allow_syncdb 需要为 model._meta.app_label == 'app2' 和 db == 'mydb' 返回 None(而不是 False)。这样 App2DBRouter.allow_syncdb 就有机会被调用。
我让您的 syncdb 使用以下更改
class App1DBRouter(object):
...
def allow_syncdb(self,db, model):
if db == 'mydb':
if model._meta.app_label == 'app1':
return True
elif model._meta.app_label == 'app1':
return False
return None
class App2DBRouter(object):
...
def allow_syncdb(self,db, model):
if db == 'mydb':
if model._meta.app_label == 'app2':
return True
else:
return False
elif model._meta.app_label == 'app2':
return False
return None
【讨论】:
那么我应该输入def allow_syncdb(self,db, model): if db == 'mydb': return model._meta.app_label in ['app1', 'app2'] elif...
之类的内容以避免使用更多路由器吗?那么,我应该把这个文件放在哪里呢?
我会把它放在名为“core”的应用程序中。但是你可能会找到一个不同的地方(取决于你的整体 Django 项目结构)。将文件命名为 routers.py 也是一个好习惯以上是关于使用数据库路由器在应用程序 Django 之间共享(mysql)数据库的主要内容,如果未能解决你的问题,请参考以下文章
如何在 django 服务器和 python websocket 服务器之间共享数据
Django在多个项目之间共享相同用户模型和数据库的最佳方式
Django Channels 是不是使用 ws:// 协议前缀在 Django 视图或 Channels 应用程序之间进行路由?