Hi,
I am trying to do the following:
Lets say i have
model A:
pass
model B:
a_val=ManyToMany(A)
c_val=ForeignKey(C)
model C:
a_val=ManyToMany(A)
obj=A()
obj_b=B()
obj_b.a_val.add(obj)
But I want to check a condition that C
should have the A
object obj
before adding it to B
.
To do so I tried adding pre_save
signal but that did not help since save is not called when adding m2m.
What I am looking for is a way to override add
method of RelatedManager
so that I can check my conditions and then call super.add()
I am unable to override the same. Also note that I only want to do this for a particular field’s RelatedManager
and not all of the field’s.
I need A in both B and C. I want to check that all the A’s in B are a subset of all the A’s in C. If not then add will throw error
I don’t know how to approach this in the way you’re looking to do, but if I had to solve this, I’d be doing it slightly differently.
My first thought on solving this would be to explicitly define the through
table for the B-to-A many-to-many relationship, and add rows to that table - overriding the save
method for it to perform my check.
(My other thought is to re-evaluate my model structure to determine if this is the most appropriate way to model the required entities.)
If it’s possible, I agree with @KenWhitesell’s suggestion to re-evaluate the model structure. For example if denormalize your model to include the many-to-many intermediate models it would look like this:
model A:
pass
model AB:
a = ForeignKey(A)
b = ForeignKey(B)
model B:
a_val=ManyToMany(A, through=AB)
c_val=ForeignKey(C)
model AC:
a = ForeignKey(A)
c = ForeignKey(C)
model C:
a_val=ManyToMany(A, through=AC)
You’re requirement is to require at least one instance of AC
before setting B.c_val
. One way to model that in your database would be to move the B.c_val
field into AB
and change it to reference AC
. See the following:
model A:
pass
model AB:
b = ForeignKey(B, null=False)
# By refencing the intermediate model here, you force a
# relationship to exist between A and C.
ac = ForeignKey(AC, null=True)
model B:
pass
model AC:
a = ForeignKey(A)
c = ForeignKey(C)
model C:
a_val=ManyToMany(A, through=AC)
As mentioned in the comment, AB.ac
forces the relationship between A and C to exist before allowing C
to be related to B
. If you want, you can drop the AB
model in favor of:
model B:
acs = ManyToMany(AC)
Even if what I suggest doesn’t work for you (it makes a bunch of assumptions about your application), I think you might be able to find a way to enforce your data integrity within your data model rather than through application logic.