Conflict in wrap_many_related_manager_add() When Using Tenant Models in M2M Relationships
Description
We've encountered an issue with the wrap_many_related_manager_add() function, where it forcefully sets the tenant field in through_defaults for many-to-many relationships.
This results in a TypeError when the tenant field (tenant_id) is already set by other parts of the application. This issue occurs specifically when adding objects to a many-to-many field on a tenant model where the tenant context is inherently managed.
Expected Behavior
The add method should intelligently handle the presence of tenant fields in through_defaults, avoiding conflicts by not overwriting existing tenant identifiers.
Current Behavior
When the tenant field is already included in through_defaults, the wrap_many_related_manager_add() function still attempts to set it, leading to a TypeError due to multiple values for keyword argument tenant_id.
Steps to Reproduce
- Define a many-to-many relationship in a tenant model where
tenant_idis a critical field. - Use
.add()to add an object to this relationship while the tenant context is set. - Observe that adding an object results in a TypeError if
tenant_idis already specified.
Suggested Fix
Modify the wrap_many_related_manager_add() function to check if the tenant field is already present in through_defaults before setting it:
def wrap_many_related_manager_add(many_related_manager_add):
def add(self, *objs, through_defaults=None):
if hasattr(self.through, "tenant_field"):
tenant_field = get_tenant_column(self.through)
current_tenant = get_current_tenant_value()
through_defaults = through_defaults or {}
if tenant_field not in through_defaults:
through_defaults[tenant_field] = current_tenant
return many_related_manager_add(self, *objs, through_defaults=through_defaults)
return add
I have submitted a PR https://github.com/citusdata/django-multitenant/pull/217