1

Django 并没有为我们管理我们的数据库,因此我创建了一个表RulesetRuleMap来处理和之间的关系ManyToMany:每个可以由多个组成,每个可以在多个.RulesetRuleRulesetRulesRuleRulesets

楷模

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

在主页上,用户可以添加/修改 aRuleset和添加/修改关联的Rules. 在提交时,我们会收到这样的有效载荷:

{
  "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"
    }
  ]
}

Djange REST Frameworkcreate()中所述,我为嵌套定义了一个自定义RulesetSerializer来处理多个对象的创建。根据Django一个应该能够

使用 add()、create() 或 set() 创建关系,只要您为任何必填字段指定 through_defaults。

执行时ruleset.rules.add(*rules_storage, through_defaults={})出现错误

{TypeError}add() got an unexpected keyword argument 'through_defaults'

执行时ruleset.rules.add(*rules_storage)出现错误

{AttributeError}Cannot use add() on a ManyToManyField which specifies an intermediary model.Use database_models.TcRulesetRuleMap's Manager instead.

我的模型和/或序列化程序设置是否有错误,或者 django 中是否有错误?

4

2 回答 2

0

我误读了 django 文档。我在 django 2.1 上,并且仅在 2.2 中引入了直通字段。

于 2020-09-17T07:40:18.260 回答
0

正如那里所说:

不能在指定中间模型的 ManyToManyField 上使用 add()。

您已经通过模型指定了自己RulesetRuleMap的对象,因此您需要自己创建对象,因为 django 不支持add()这种情况。

如果您想使用add(),create()或者set()根据下面列出的文档,您需要through_defaults为任何必填字段传递 kwarg。您没有任何额外的必填字段,因此需要对您的特定模型集进行调试。

与直通模型的这种关系的 DRF 文档在这里

在 django 文档中有一个很好的例子,可以在这里使用直通模型设置对象

在示例中,有 3 个模型PersonGroupMembershipGroup有M2M可以Person通过Membership

>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
...     date_joined=date(1962, 8, 16),
...     invite_reason="Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>]>
>>> ringo.group_set.all()
<QuerySet [<Group: The Beatles>]>
>>> m2 = Membership.objects.create(person=paul, group=beatles,
...     date_joined=date(1960, 8, 1),
...     invite_reason="Wanted to form a band.")
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>
于 2020-09-16T11:04:18.783 回答