citusdata / citusdata/django-multitenant

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

Open
#216 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
823
Forks
126
PR merge metrics
No merged PRs in 30d

Description

## 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_id` is 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_id` is 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
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.