我让django在oracle后台运行。我需要使用两个模式-一个用于遗留DB,另一个用于所有与django相关的表。
这就是我的settings.DATABASES:
APPS_DB = 'apps'
DATABASES = {
'default' : {
'ENGINE': 'django.db.backends.oracle'
'NAME': 'django',
'USER': 'django-tables',
'PASSWORD': '****',
'HOST': 'localhost',
'PORT': '1531',
},
APPS_DB : {
'ENGINE': 'django.db.backends.oracle',
'NAME': 'django',
'USER': 'legacy-stuff',
'PASSWORD': '****',
'HOST': 'localhost',
'PORT': '1531',
},
}我还定义了路由器:
class MyRouter(object):
"""A router to control all database operations on models"""
def __init__(self):
aux = []
for app in settings.INSTALLED_APPS:
if not app.endswith('myapp'):
aux.append(app)
self.djangoStuff = tuple(map(lambda x: x[x.rfind('.')+1:], aux))
def is_django_stuff(self, model):
return model._meta.app_label in self.djangoStuff
def db_for_read(self, model, **hints):
"Point all django apps models to separate DB"
logger.info("READ from " + model._meta.app_label)
if self.is_django_stuff(model):
logger.info("Will be directed to default DB")
return None
logger.info("Will be directed to legacy DB")
return settings.APPS_DB
def db_for_write(self, model, **hints):
"Point all django apps models to separate DB"
logger.info("WRITE")
if self.is_django_stuff(model):
return None
return settings.APPS_DB
def allow_relation(self, obj1, obj2, **hints):
"Allow any relation"
logger.info("ALLOW REL")
return True
def allow_syncdb(self, db, model):
"Allow syncdb for all managed objects"
logger.info("ALLOW SYNC")
if db == 'default' and self.is_django_stuff(model):
return True
if db != 'default' and not self.is_django_stuff(model):
return True
return False现在我有了一个非常简单的模型:
class Poll(models.Model):
question = models.CharField(max_length=200)
user = models.ForeignKey(User)
pub_date = models.DateTimeField('date published')我创建了两个syncdb:
python manage.py syncdb
python manage.py syndb --database apps一切都很顺利。然后,我使用'python manage.py shell‘创建了投票对象
superuser = User.objects.all()[0]
p = Poll(question="foo", user = superuser, pub_date = datetime.now())
p.save()我尝试从投票中检索用户:
a = Poll.objects.all()
b = len(a)
b = a[0]
c = b.artist我在路由器中启用了日志记录,因此我看到最后一个查询将被定向到正确的DB:
READ from myapp
Will be directed to apps DB
READ from myapp
Will be directed to apps DB
READ from auth
Will be directed to default DB我甚至可以看到实际的SQL语句:
(0.005) SELECT "AUTH_USER"."ID", "AUTH_USER"."USERNAME", "AUTH_USER"."FIRST_NAME", "AUTH_USER"."LAST_NAME", "AUTH_USER"."EMAIL", "AUTH_USER"."PASSWORD", "AUTH_USER"."IS_STAFF", "AUTH_USER"."IS_ACTIVE", "AUTH_USER"."IS_SUPERUSER", "AUTH_USER"."LAST_LOGIN", "AUTH_USER"."DATE_JOINED" FROM "AUTH_USER" WHERE "AUTH_USER"."ID" = :arg0 ; args=(1,)但是我得到了一个错误:
File "<console>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.1-py2.7.egg/django/db/models/fields/related.py", line 350, in __get__
rel_obj = qs.get(**params)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.1-py2.7.egg/django/db/models/query.py", line 361, in get
num = len(clone)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.1-py2.7.egg/django/db/models/query.py", line 85, in __len__
self._result_cache = list(self.iterator())
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.1-py2.7.egg/django/db/models/query.py", line 291, in iterator
for row in compiler.results_iter():
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.1-py2.7.egg/django/db/models/sql/compiler.py", line 763, in results_iter
for rows in self.execute_sql(MULTI):
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.1-py2.7.egg/django/db/models/sql/compiler.py", line 818, in execute_sql
cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.1-py2.7.egg/django/db/backends/util.py", line 40, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.1-py2.7.egg/django/db/backends/oracle/base.py", line 675, in execute
return self.cursor.execute(query, self._param_generator(params))
DatabaseError: ORA-00942: table or view does not exist所以我的问题是--我做错了什么?
发布于 2012-10-22 05:23:51
跨数据库外键本质上是无效的,因为Django正在建模一个具有引用完整性的“适当的”关系数据库,如果模型存储在完全不同的物理存储中,则不能在数据库级别强制执行。
无论如何,由于这个原因,Django必须假设任何对象都存在于您最初检索到的数据库中。在您的例子中,它从您的遗留数据库中获取了Poll对象,因此它也必须在那里查找您的用户(或艺术家或其他任何人)。
对于像这样的简单查询,它很容易解决,例如:
poll = Poll.objects.all()[0]
user_id = poll.user_id # _id after the name of your "Foreign Key" field - which cannot really be an FK
user = User.objects.get(user_id) # This will be a new query and can use a different database, it will check the router对于更复杂的查询(连接等),您通常会发现需要构建ids列表或ids集,并使用filter(id__in=your_list_of_ids)进行查询。
根据记录数的不同,这样做可能会对性能或内存使用造成影响。(但在某些情况下,您的查询实际上会比原始连接快得多,这完全取决于您的应用程序。)你可能需要把你的id列表分成几批,或者你的查询可能会变得太长,等等,但是这些问题都不是无法克服的。
当您处理来自另一个数据库的id时,应该由您来执行引用完整性。有时,您需要设置批处理过程来处理整理数据。
这一切听起来都是错误的,但这种关注点分离,特别是如果您可以限制依赖,并且只在一个方向上,则可能是正确的方法。
https://stackoverflow.com/questions/12862541
复制相似问题