简体   繁体   中英

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. There are no A objects yet (at least with id=1 ).

I try to create object B using the id of some hypothetical object A fetched from the 3rd party.

Expectation

If there is no object A -> IntegrityError is thrown -> deal with it (eg create object A with id=1 and rerun).

Reality

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. 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)


EDIT 1

As it turns out, the problem is with pytest. Only inside test I can't catch 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 . Nonetheless IntegrityError 's traceback is printed out in the console. And object b is created.

The problem was with trying to catch IntegrityError inside an atomic transaction.

Guys from pytest helped to fix it @pytest.mark.django_db(transaction=True) instead of just @pytest.mark.django_db .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM