citusdata / django-multitenant

Python/Django support for distributed multi-tenant databases like Postgres+Citus
MIT License
707 stars 116 forks source link

Conflict in wrap_many_related_manager_add() When Using Tenant Models in M2M Relationships #216

Open rob101 opened 2 months ago

rob101 commented 2 months ago

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

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
rob101 commented 2 months ago

I have submitted a PR https://github.com/citusdata/django-multitenant/pull/217