下面的代码:
print(f"current database: {self.db}\ninfusate from database: {infusate._state.db}\ntracer from database: {tracer._state.db}")
FCirc.objects.using(self.db).get_or_create(
serum_sample=sample,
tracer=tracer,
element=label.element,
)
生成以下输出和异常:
current database: validation
infusate from database: validation
tracer from database: validation
Validating FCirc updater: {'update_function': 'is_last_serum_peak_group', 'update_field': 'is_last', 'parent_field': 'serum_sample', 'child_fields': [], 'update_label': 'fcirc_calcs', 'generation': 2}
Traceback (most recent call last):
File "/Users/rleach/PROJECT-local/TRACEBASE/tracebase/.venv/lib/python3.9/site-packages/django/db/models/query.py", line 581, in get_or_create
return self.get(**kwargs), False
File "/Users/rleach/PROJECT-local/TRACEBASE/tracebase/.venv/lib/python3.9/site-packages/django/db/models/query.py", line 435, in get
raise self.model.DoesNotExist(
DataRepo.models.fcirc.FCirc.DoesNotExist: FCirc matching query does not exist.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/rleach/PROJECT-local/TRACEBASE/tracebase/DataRepo/views/loading/validation.py", line 91, in validate_load_files
call_command(
File "/Users/rleach/PROJECT-local/TRACEBASE/tracebase/.venv/lib/python3.9/site-packages/django/core/management/__init__.py", line 181, in call_command
return command.execute(*args,**defaults)
File "/Users/rleach/PROJECT-local/TRACEBASE/tracebase/.venv/lib/python3.9/site-packages/django/core/management/base.py", line 398, in execute
output = self.handle(*args,**options)
File "/Users/rleach/PROJECT-local/TRACEBASE/tracebase/DataRepo/management/commands/load_animals_and_samples.py", line 134, in handle
loader.load_sample_table(
File "/Users/rleach/PROJECT-local/TRACEBASE/tracebase/DataRepo/utils/sample_table_loader.py", line 426, in load_sample_table
FCirc.objects.using(self.db).get_or_create(
File "/Users/rleach/PROJECT-local/TRACEBASE/tracebase/.venv/lib/python3.9/site-packages/django/db/models/query.py", line 588, in get_or_create
return self.create(**params), True
File "/Users/rleach/PROJECT-local/TRACEBASE/tracebase/.venv/lib/python3.9/site-packages/django/db/models/query.py", line 451, in create
obj = self.model(**kwargs)
File "/Users/rleach/PROJECT-local/TRACEBASE/tracebase/DataRepo/models/maintained_model.py", line 430, in __init__
super().__init__(*args,**kwargs)
File "/Users/rleach/PROJECT-local/TRACEBASE/tracebase/.venv/lib/python3.9/site-packages/django/db/models/base.py", line 485, in __init__
_setattr(self, field.name, rel_obj)
File "/Users/rleach/PROJECT-local/TRACEBASE/tracebase/.venv/lib/python3.9/site-packages/django/db/models/fields/related_descriptors.py", line 229, in __set__
raise ValueError('Cannot assign "%r": the current database router prevents relation between database "%s" and "%s".' % (value, instance._state.db, value._state.db))
ValueError: Cannot assign "<Tracer: lysine-[13C6]>": the current database router prevents this relation.
Cannot assign "<Tracer: lysine-[13C6]>": the current database router prevents this relation.
由于知道这个错误与不同数据库中记录之间的外部关系有关,所以作为一种健全性检查,我修改了related_descriptors.py
的源代码以包含更多信息:
raise ValueError('Cannot assign "%r": the current database router prevents relations between database "%s" and "%s".' % (value, instance._state.db, value._state.db))
上面写着:
Cannot assign "<Tracer: lysine-[13C6]>": the current database router prevents relations between database "default" and "validation".
所以我要疯了。为什么它忽略了我的.using(self.db)
呼叫?!
然后我意识到,“哦,是的--我在超类中覆盖了__init__
到FCirc!我可能是在绕过using(db)
。"
class FCirc(MaintainedModel, HierCachedModel):
...
class MaintainedModel(Model):
...
在两个超类混合中,MaintainedModel
似乎是这个例子中的罪魁祸首。它是唯一一个覆盖__init__
的超类。覆盖如下:
def __init__(self, *args,**kwargs):
"""
This over-ride of the constructor is to prevent developers from explicitly setting values for automatically
maintained fields. It also performs a one-time validation check of the updater_dicts.
"""
# ... about 80 lines of code that I'm very confident are unrelated to the problem. See the docstring above. Will paste upon request ...
# vvv THIS LINE IS LINE 430 FROM maintained_model.py IN THE TRACE ABOVE
super().__init__(*args,**kwargs)
如何在超级构造函数中沿着self.db?
1条答案
按热度按时间798qvoo81#
我发现了!另一个开发者在
QuerySet
类的派生类中为一些模型添加了对full_clean
(which I have a separate question about)的调用。例如:这些对
full_clean
的调用 * 看起来 * 只能在默认数据库上工作。至少,我还不知道如何告诉full_clean
在我们的验证数据库上操作。如果当前数据库是默认数据库,我将找到的
QuerySet
派生类的3或4个调用更改为仅调用full_clean
:在此之后,我不再得到
FCirc
get_or_create
调用上的异常,并且操作的数据库是验证数据库。我很好奇是否有其他数据库操作被分配给了默认数据库,所以我在
django.db.utils.py: _router_func
中的另一段代码中添加了一个debug print:这显示了另外两个地方正在查询默认数据库,而我知道它应该只查询验证数据库。
这一个很有意义,因为它是一个新的数据库查询:
所以我修改了它,改为使用当前数据库(基于示例):
我将这个添加到我的MaintainedModel类中:
这是可行的,但是我不喜欢它要求开发人员在派生类中包含特定于超类的代码。另外,
settings.DEFAULT_DB
是特定于项目的,所以它创建了一个相互依赖关系。我真正需要做的是改变django基础代码在没有明确指定数据库时设置的默认数据库...
我敢打赌,这很容易做到。我只是从来没有这样做过。我会开始研究,我可能会修改这个答案很快。
上一个“答案”
好吧,这并不是一个真正的答案,因为我不希望开发人员不得不跳过这些可笑的障碍,在一个继承自
MaintainedModel
的模型上使用get_or_create,但它解决了这个问题。它防止了异常,并且所有内容都被应用到正确的数据库中。也许这会给予其他人一个提示,告诉他们如何正确地解决MaintainedModel中
__init__
构造函数的重写内部的问题:输出为: