Relatedobject manager override add method

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.