【问题标题】:Django rest framework - Foreign key - one to many relationDjango 休息框架 - 外键 - 一对多关系
【发布时间】:2022-01-07 22:03:35
【问题描述】:

对于我的项目,我需要一个简单的流程 一个表单 => 许多问题 => 对于每个问题一个响应类型 => 如果响应类型是多项选择,则可能的响应在一个 uniq 组中。 我的目标是能够推动整个初始形式的 DRF/Django 休息框架。

这是我的模型:

class FormModels(models.Model):

    class Status(models.IntegerChoices):
        DRAFT = 1, _("DRAFT")
        PUBLISHED = 2, _("PUBLISHED")
        ARCHIVED = 5, _("ARCHIVED")

    form_name = models.CharField(unique=True, blank=False, null=False, max_length=255)
    form_model = models.CharField(unique=True, blank=False, null=False, max_length=255)
    status = models.IntegerField(choices=Status.choices, blank=False, null=False, default=1)

    def __str__(self):
        return self.form_name

class FormResponseTypeModels(models.Model):
    
    class Type(models.IntegerChoices):
        TEXT = 1, _('TEXT')
        MULTICHOICE = 2, _('MULTI')

    type = models.IntegerField(choices=Type.choices, blank=False, null=False, default=1)
    group = models.IntegerField(blank=False, null=True, default=1)

    def __str__(self):
        return str(self.type)

    class Meta:
        constraints = [
            UniqueConstraint(fields=['group'], name='unique_group')
        ]

class MultipleChoiceDataModels(models.Model):
    
    text = models.CharField(blank=False, null=False, max_length=255)
    value = models.CharField(blank=False, null=False, max_length=255)
    order = models.IntegerField(blank=False, null=False, default=1)
    group_refid = models.ForeignKey(blank=False,
                                    null=False,
                                    default=1,
                                    to=FormResponseTypeModels,
                                    to_field="group",
                                    related_name="groups",
                                    on_delete=models.PROTECT)

    def __str__(self):
        return self.text

class FormQuestionModels(models.Model):
    
    form_id = models.ForeignKey(to=FormModels, on_delete=models.PROTECT)
    form_response_type = models.ForeignKey(to=FormResponseTypeModels, on_delete=models.PROTECT, related_name="test")
    form_question = models.TextField(max_length=2000)

    def __str__(self):
        return self.form_question

这是我的 serializers.py

​​>
class FormMultipleChoiceDataSerializer(serializers.ModelSerializer):
    class Meta:
        model = MultipleChoiceDataModels
        fields = "__all__"
        depth = 10


class FormResponseTypeSerializer(serializers.ModelSerializer):
    groups = FormMultipleChoiceDataSerializer(many=True,
                                              read_only=False,
                                              required=False,
                                              )

    class Meta:
        model = FormResponseTypeModels
        fields = "__all__"
        depth = 10


class FormQuestionSerializer(serializers.ModelSerializer):
    form_response_type_set = FormResponseTypeSerializer(many=False,
                                                        read_only=False,
                                                        required=False
                                                        )

    class Meta:
        model = FormQuestionModels
        fields = "__all__"
        depth = 10


class FormSerializer(serializers.HyperlinkedModelSerializer):
    questions = FormQuestionSerializer(many=True,
                                       read_only=False,
                                       source='formquestionmodels_set',
                                       required=False)

    class Meta:
        model = FormModels
        fields = "__all__"

    def validate(self, attrs):
        pass
        return super().validate(attrs=attrs)

    def create(self, validated_data):
        # https://stackoverflow.com/questions/58023503/drf-serializer-field-renamed-to-its-source-in-validated-data
        # question is 'formquestionmodels_set'
        questions_data = validated_data.pop('formquestionmodels_set')
        form = FormModels.objects.create(**validated_data)
        for question_data in questions_data:
            if "form_response_type_set" in questions_data:
                form_response_type_set = question_data.pop("form_response_type_set")
                max_group_id = None
                if "formmultiplechoicedatamodel_set" in form_response_type_set:
                    form_response_type_set_groups = form_response_type_set.pop("formmultiplechoicedatamodel_set")
                    # find max group_id + 1
                    max_group_id = 1 + MultipleChoiceDataModels.objects.aggregate(Max("group_refid"))
                    for form_response_type_set_group in form_response_type_set_groups:
                        MultipleChoiceDataModels.objects.create(group_refid=max_group_id,
                                                                **form_response_type_set_group)
                if max_group_id:
                    form_response_type = FormResponseTypeModels.objects.create(group=max_group_id,
                                                                               **form_response_type_set)
                else:
                    form_response_type = FormResponseTypeModels.objects.create(**form_response_type_set)

                FormQuestionModels.objects.create(form_id=form, form_response_type=form_response_type, **question_data)
        return form

预期结果是:

{
"form_name": "test7",
"form_model": "test7",
"status": 1,
"questions": [
    {
        "form_question": "q1",
        "form_response_type_set": {
            "type": 1,
            "group": [
                {
                    "text": "a",
                    "value": "1",
                    "order": 1,
                    "group_refid": 1
                }
            ]
        }
    },
    {
        "form_question": "q2",
        "form_id": {
            "form_name": "form_name",
            "form_model": "form_model",
            "status": 1
        },
        "form_response_type_set": {
            "type": 1,
            "group": [
                {
                    "text": "a",
                    "value": "1",
                    "order": 1,
                    "group_refid": 1
                }
            ]
        }
    }
]

}

但是对于组部分,我无法显示它。我得到了:

"questions": [
            {
                "id": 1,
                "form_question": "q1",
                "form_id": {
                    "id": 1,
                    "form_name": "t1",
                    "form_model": "t1",
                    "status": 2
                },
                "form_response_type": {
                    "id": 1,
                    "type": 1,
                    "group": null
                }
            },
            {
                "id": 2,
                "form_question": "q2",
                "form_id": {
                    "id": 1,
                    "form_name": "t1",
                    "form_model": "t1",
                    "status": 2
                },
                "form_response_type": {
                    "id": 2,
                    "type": 2,
                    "group": 1
                }
            }
        ],
        "form_name": "t1",
        "form_model": "t1",
        "status": 2
    }
]

使用 django shell 我得到这个结果:

FormResponseTypeSerializer():
id = IntegerField(label='ID', read_only=True)
groups = FormMultipleChoiceDataSerializer(many=True, read_only=False, required=False):
    id = IntegerField(label='ID', read_only=True)
    text = CharField(max_length=255)
    value = CharField(max_length=255)
    order = IntegerField(max_value=2147483647, min_value=-2147483648, required=False)
    group_refid = NestedSerializer(read_only=True):
        id = IntegerField(label='ID', read_only=True)
        type = ChoiceField(choices=[(1, 'TEXT'), (2, 'MULTI')], required=False, validators=[<django.core.validators.MinValueValidator object>, <django.core.validators.MaxValueValidator object>])
        group = IntegerField(allow_null=True, max_value=2147483647, min_value=-2147483648, required=False)
type = ChoiceField(choices=[(1, 'TEXT'), (2, 'MULTI')], required=False, validators=[<django.core.validators.MinValueValidator object>, <django.core.validators.MaxValueValidator object>])
group = IntegerField(allow_null=True, max_value=2147483647, min_value=-2147483648, required=False)

我已经尝试过源和相关名称、许多类型的序列化程序、变量源的 _set 语法 ... ,阅读了 40 多个堆栈溢出线程,但每次我都被这个问题困扰(另外,如果重要的话,我希望能够使用相同的端点一次发布新表单)

你能指出我的错误吗?

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    我不确定我做了什么让它工作,但经过多次尝试

    • 在模型中使用related_name
    • 更改字段名称以避免使用文本、值和顺序,
    • 删除数据库并再次应用迁移,
    • depth=1 设置为每个父序列化程序。

    现在可以了!

    如果有人有很好的解释,我很乐意阅读并学习!

    【讨论】:

      猜你喜欢
      • 2021-05-14
      • 2019-08-06
      • 1970-01-01
      • 2018-08-23
      • 2017-02-03
      • 2013-05-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多