Opened 8 years ago

Closed 6 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: Gergely Kontra 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 Russell Keith-Magee)

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 Gaynor

Needs documentation: unset
Needs tests: unset
Patch needs improvement: unset
Triage Stage: UnreviewedAccepted

Marking as accepted because it makes sense.

comment:2 Changed 8 years ago by Russell Keith-Magee

Description: modified (diff)
Summary: Allow add/create if all the non-FK fields have defaults or are NULLableAllow 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 (none)

milestone: post-1.0

Milestone post-1.0 deleted

comment:5 Changed 6 years ago by Luke Plant

Severity: Normal
Type: New feature

comment:6 Changed 6 years ago by Johannes Dollinger

Easy pickings: unset
Resolution: duplicate
Status: newclosed

Duplicate of #9475.

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