[英]How to disallow creation of object if related foreign key doesn't exists?
Here is the setup 这是设置
class A(Model):
pass
class B(Model):
a = ForeignKey(A, on_delete=CASCADE)
assert A.objects.all().count() == 0
try:
B.object.create(a_id=1)
except IntegrityError:
print('error')
# ... another logic to deal with situation
DB is PostgreSQL. DB是PostgreSQL。 There are no
A
objects yet (at least with id=1
). 尚无
A
对象(至少id=1
)。
I try to create object B
using the id of some hypothetical object A
fetched from the 3rd party. 我尝试使用从第三方获取的某些假设对象
A
的ID创建对象B
If there is no object A
-> IntegrityError is thrown -> deal with it (eg create object A
with id=1
and rerun). 如果没有对象
A
>引发IntegrityError->处理它(例如,创建id=1
对象A
并重新运行)。
Object B
is created anyway despite having a foreign key constraint, IntegrityError ( Key (a_id)=(1) is not present in table "app_a"
) is thrown but is not fetched by try/except. 尽管具有外键约束,还是创建了对象
B
,但抛出了IntegrityError( Key (a_id)=(1) is not present in table "app_a"
),但是try / except并未获取它。 Everything is messed up. 一切都搞砸了。
I don't what to get_or_create
object A
beforehand because I will end up with 2 queries every time I want to create B
(and I need to create it many times while most of the time needed object A
is already in DB) 我没有什么
get_or_create
对象A
因为每次我要创建B
时都会以2个查询结束(而且我需要多次创建它,而大多数时候所需的对象A
已经在数据库中)
As it turns out, the problem is with pytest. 事实证明,问题出在pytest上。 Only inside test I can't catch
IntegrityError
. 仅在测试中,我无法捕获
IntegrityError
。
with pytest.raises(IntegrityError):
b = B.objects.create(a_id=1)
Code above didn't raise IntegrityError
despite the absence of A
object with id=1
. 尽管缺少
id=1
的A
对象,但是上面的代码并未引发IntegrityError
。 Nonetheless IntegrityError
's traceback is printed out in the console. 尽管如此,
IntegrityError
的回溯还是在控制台中打印出来。 And object b
is created. 并创建对象
b
。
The problem was with trying to catch IntegrityError
inside an atomic transaction. 问题在于试图在原子事务中捕获
IntegrityError
。
Guys from pytest
helped to fix it @pytest.mark.django_db(transaction=True)
instead of just @pytest.mark.django_db
. pytest
家伙帮助修复了@pytest.mark.django_db(transaction=True)
而不仅仅是@pytest.mark.django_db
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.