Prevent related object persistence in sqlalchemy
Question:
Environment
- Python 3.8.10
- SQLAlchemy 1.3.22
Problem
I am having a problem related to the stated here, but couldn’t find a solution yet: How to prevent related object persistence in sqlalchemy?
I have two models with a one to many relationship:
class A:
b = db.relationship("B", back_populates="a", cascade="all,delete")
class B:
a_id = db.Column('A_ID', db.Integer, db.ForeignKey('A.ID'), nullable=False)
a = db.relationship('A', back_populates="b")
The thing is that at a certain point, I need to modify a certain field of B. To do so, I need to access the object A related to the current B object to do some checks. But, as A is a class that uses translations and we need to have that in mind.
What translate
does is overwrite the translatable fields of A in the current instance, without storing them in the database (we have the translations on a diferent table due to backwards compatibility). I need to do that translation to do the checks and get the correct value I should set to B. The problem is as follows:
# some_service.py
def get_by_id(a_id):
a = A.get_by_id(a_id)
if a:
return translate(a)
# file_y.py
def get_value_to_update_b(a_id)
a = some_service.get_by_id(a_id)
# do some stuff without saving anything to A
# file_x.py
b = B.get_by_id(id) # At this point, b.a stores the original A object
value = file_y.get_value_to_update_b(b.a_id) # After this executes, b.a points to the translated one, instead of the original, so when B is saved, the translated A is saved too.
b.value = value
session.add(b)
session.commit()
As you can see, the problem is that when I translate A to do the checks, the reference from B gets updated to A_translated
, so when I save B, A is saved too with the translated values, which is incorrect.
I have already tried modifying the cascade
attribute of the relationships (to None
and merge
), making a copy of the object A before translating and some other choices. And changing the whole translation process, although a possibility, it’s something I would rather have as the last option as this is something that urges us.
Is there anything else I could do to prevent A being saved when B is saved? If you have any question about the process, as I think it can be a little bit messy, I would gladly answer you. Thank you very much
Answers:
In the end I ended up with another approach. I couldn’t find a solution for the simultaneous storing of A and B, but I just made the checks different so the translation didn’t overwrite the original instance.
Environment
- Python 3.8.10
- SQLAlchemy 1.3.22
Problem
I am having a problem related to the stated here, but couldn’t find a solution yet: How to prevent related object persistence in sqlalchemy?
I have two models with a one to many relationship:
class A:
b = db.relationship("B", back_populates="a", cascade="all,delete")
class B:
a_id = db.Column('A_ID', db.Integer, db.ForeignKey('A.ID'), nullable=False)
a = db.relationship('A', back_populates="b")
The thing is that at a certain point, I need to modify a certain field of B. To do so, I need to access the object A related to the current B object to do some checks. But, as A is a class that uses translations and we need to have that in mind.
What translate
does is overwrite the translatable fields of A in the current instance, without storing them in the database (we have the translations on a diferent table due to backwards compatibility). I need to do that translation to do the checks and get the correct value I should set to B. The problem is as follows:
# some_service.py
def get_by_id(a_id):
a = A.get_by_id(a_id)
if a:
return translate(a)
# file_y.py
def get_value_to_update_b(a_id)
a = some_service.get_by_id(a_id)
# do some stuff without saving anything to A
# file_x.py
b = B.get_by_id(id) # At this point, b.a stores the original A object
value = file_y.get_value_to_update_b(b.a_id) # After this executes, b.a points to the translated one, instead of the original, so when B is saved, the translated A is saved too.
b.value = value
session.add(b)
session.commit()
As you can see, the problem is that when I translate A to do the checks, the reference from B gets updated to A_translated
, so when I save B, A is saved too with the translated values, which is incorrect.
I have already tried modifying the cascade
attribute of the relationships (to None
and merge
), making a copy of the object A before translating and some other choices. And changing the whole translation process, although a possibility, it’s something I would rather have as the last option as this is something that urges us.
Is there anything else I could do to prevent A being saved when B is saved? If you have any question about the process, as I think it can be a little bit messy, I would gladly answer you. Thank you very much
In the end I ended up with another approach. I couldn’t find a solution for the simultaneous storing of A and B, but I just made the checks different so the translation didn’t overwrite the original instance.