#32011 closed Bug (invalid)
Error when calling add() on ManyRelatedManager with intermediary model
Reported by: | Philipp Maino | Owned by: | nobody |
---|---|---|---|
Component: | Documentation | Version: | 2.1 |
Severity: | Normal | Keywords: | ManyToMany, ManyRelatedManager |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Django is not managing our databases for us, therefor I created the table RulesetRuleMap to handle the ManyToMany relationship between Ruleset and Rule: Each Ruleset can consist of multiple Rules and each Rule can be used in multiple Rulesets.
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 DRF I defined a custom create() for the nested RulesetSerializer to handle the creation of multiple objects. According to / 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?
Change History (2)
follow-up: 2 comment:1 by , 4 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:2 by , 4 years ago
Replying to felixxm:
through_defaults
was added in Django 2.2, please use 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:
through_defaults
was added in Django 2.2, please use documentation for the version you're using.