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
.
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'
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 Djange REST Framework 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?
I misread the django docs. I'm on django 2.1 and the through fields were only introduced in 2.2.