Opened 8 years ago

Closed 5 years ago

#8334 closed New feature (duplicate)

Allow add/create on m2m intermediate tables if all the non-FK fields have defaults or are NULLable

Reported by: pihentagy Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords: manytomany through default add create
Cc: ales.zoulek@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX:

Description (last modified by russellm)

Add/create is currently disabled on m2m relations that use an intermediate table. This is due to the fact that values to populate the intermediate table cannot be provided using the add/create calls.

However, what if the intermediate model has reasonable default values, so
one can assign model A to B without extra info?

In my case, I just want to syncronize 2 databases, and I would like to
mark relationships, that are already synced. So, in my case, the
intermediate table contains a boolean, which defaults to false, and
will become true, when the data is synced.

In this case adding relations without explicitly creating the intermediate table would be great.

(based on this thread in the ML)

Change History (6)

comment:1 Changed 8 years ago by Alex

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

Marking as accepted because it makes sense.

comment:2 Changed 8 years ago by russellm

  • Description modified (diff)
  • Summary changed from Allow add/create if all the non-FK fields have defaults or are NULLable to Allow add/create on m2m intermediate tables if all the non-FK fields have defaults or are NULLable

Updated description and summary to describe the problem better.

comment:3 Changed 8 years ago by ales_zoulek

  • Cc ales.zoulek@… added

I did just a quick workaround. It's far from complete and universal code, but it works for me and could help some of you. :)

from django.db.models.fields.related import ReverseManyRelatedObjectsDescriptor as DjangoReverseManyRelatedObjectsDescriptor
from django.db import models

class ReverseManyRelatedObjectsDescriptor(DjangoReverseManyRelatedObjectsDescriptor):
    """Partialy supports add method in ManyToManyField with 'through'"""
    def __get__(self, *args, **kwargs):
        manager = super(ReverseManyRelatedObjectsDescriptor, self).__get__(*args, **kwargs)
        def add(*objs):
            manager._add_items(manager.source_col_name, manager.target_col_name, *objs)
        add.alters_data = True
        manager.add = add
        return manager

class ManyToManyField(models.ManyToManyField):

    def contribute_to_class(self, cls, name):
        ret = super(ManyToManyField, self).contribute_to_class(cls, name)
        setattr(cls,, ReverseManyRelatedObjectsDescriptor(self))
        return ret

# Continue with your models here. Use ManyToManyField class where needed.
class A(models.Model)
    b = ManyToManyField(B, through=AB)


comment:4 Changed 8 years ago by anonymous

  • milestone post-1.0 deleted

Milestone post-1.0 deleted

comment:5 Changed 5 years ago by lukeplant

  • Severity set to Normal
  • Type set to New feature

comment:6 Changed 5 years ago by emulbreh

  • Easy pickings unset
  • Resolution set to duplicate
  • Status changed from new to closed

Duplicate of #9475.

Note: See TracTickets for help on using tickets.
Back to Top