**Models**
{{{
class Rule(models.Model):
id = models.BigAutoField(primary_key=True)
percentage_of_total = models.FloatField(blank=False, null=False)
_rule_parameter = models.ForeignKey('RuleParameter',
models.DO_NOTHING, blank=False, null=False)
class Meta:
managed = False
db_table = '_rule'
class Ruleset(models.Model):
id = models.BigAutoField(primary_key=True)
name = models.CharField(max_length=300, blank=False, null=False)
description = models.CharField(max_length=300, blank=False,
null=False)
rules = models.ManyToManyField('Rule', through="RulesetRuleMap")
class Meta:
managed = False
db_table = '_ruleset'
class RulesetRuleMap(models.Model):
id = models.BigAutoField(primary_key=True)
_rule = models.ForeignKey('Rule', models.CASCADE)
_ruleset = models.ForeignKey('Ruleset', models.CASCADE)
class Meta:
managed = False
db_table = '_ruleset_rule_map'
}}}
**Serializers**
{{{
class RulesetRuleMapSerializer(serializers.ModelSerializer):
class Meta:
model = db_models.RulesetRuleMap
fields = '__all__'
class RuleSerializer(serializers.ModelSerializer):
class Meta:
model = db_models.Rule
fields = '__all__'
class RulesetSerializer(serializers.ModelSerializer):
rules = RuleSerializer(many=True)
class Meta:
model = db_models.Ruleset
fields = '__all__'
def create(self, validated_data):
rules_data = validated_data.pop('rules')
ruleset = db_models.Ruleset.objects.create(**validated_data)
rules_storage =[]
for rule_data in rules_data:
rule, created =
db_models.Rule.objects.get_or_create(**rule_data)
rules_storage.append(rule)
ruleset.rules.add(*rules_storage, through_defaults={})
return ruleset
}}}
On a homepage the user can add/modify a Ruleset and add/modify the
assosiated Rules. On submission we receive a payload like this:
{{{
{
"id": None,
"name": "Split_50.0_Param1_50.0_Param2",
"description": "test",
"rules": [
{
"id": None,
"percentage_of_total": "50",
"tc_rule_parameter": "3"
},
{
"id": None,
"percentage_of_total": "50",
"tc_rule_parameter": "2"
}
]
}
}}}
As described in [https://www.django-rest-framework.org/api-guide/relations
/#writable-nested-serializers/ DRF] I defined a custom create() for the
nested RulesetSerializer to handle the creation of multiple objects.
According to [https://docs.djangoproject.com/en/3.1/topics/db/models
/#extra-fields-on-many-to-many-relationships / Django] one should be able
to
----
use add(), create(), or set() to create relationships, as long as you
specify through_defaults for any required fields.
----
When executing ruleset.rules.add(*rules_storage, through_defaults={}) I
get the error
**''{TypeError}add() got an unexpected keyword argument
'through_defaults'''**
When executing ruleset.rules.add(*rules_storage) I get the error
**''{AttributeError}Cannot use add() on a ManyToManyField which specifies
an intermediary model.Use database_models.TcRulesetRuleMap's Manager
instead.''**
Is there a mistake in my model and/or serializer set up or is there a bug
in django?
--
Ticket URL: <https://code.djangoproject.com/ticket/32011>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* status: new => closed
* resolution: => invalid
Comment:
`through_defaults` was added in Django 2.2, please use
[https://docs.djangoproject.com/en/2.1/ documentation] for the version
you're using.
--
Ticket URL: <https://code.djangoproject.com/ticket/32011#comment:1>
Comment (by Philipp Maino):
Replying to [comment:1 felixxm]:
> `through_defaults` was added in Django 2.2, please use
[https://docs.djangoproject.com/en/2.1/ documentation] for the version
you're using.
Hi @felixxm, I'm very happy if that's the problem at hand. I scaned over
the docs for 2.1 and didn't this difference:
**3.1**
You can also use **add()**, **create()**, or **set()** to create
relationships, as long as you specify through_defaults for any required
fields
**2.1**
Unlike normal many-to-many fields, you can’t use** add()**,** create()**,
or** set()** to create relationships:
--
Ticket URL: <https://code.djangoproject.com/ticket/32011#comment:2>