djangorest:创建新父对象时如何设置相关字段可选

发布于 2025-02-04 11:42:14 字数 3573 浏览 0 评论 0原文

在这里,我有两个模型:文档和Mysource,MySource将文档作为外国关键领域。为了总结该关系,用一个空数阵列的MySource对象初始化了文档,用户可以在其中创建一个新的MySource对象。

我正在尝试找出一种使用以下帖子请求创建文档对象的方法,其中MySource字段在开始时可以选择或空。

POST REQUEST
{
  "title": "Untitled",
  "templateId": 30,
  "question_blocks": [],
  "outline_blocks": [],
}

这将给出错误消息:“需要MySource字段”,

POST REQUEST
{
  "title": "Untitled",
  "templateId": 30,
  "question_blocks": [],
  "outline_blocks": [],
  "mysource": []
}

这将给出错误消息:直接分配到相关集的反向侧。使用adveress.set()而不是

models.py

class Document(models.Model):
    id = HashidAutoField(primary_key=True)
    # TODO: blank, null to False
    user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
    title = models.CharField(max_length=100, default="Untitled")
    template = models.CharField(max_length=100, default="")
    editorState = models.JSONField(default=[])
    updated = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

class MySource(models.Model):
    id = models.AutoField(primary_key=True)
    document = models.ForeignKey(
        Document,
        related_name="mysource",
        on_delete=models.CASCADE,
        null=True,
        blank=True,
    )
    documentId = models.CharField(max_length=50, default="", blank=True)
    url = models.CharField(max_length=500, default="", blank=True)
    title = models.CharField(max_length=500, default="", blank=True)
    publisher = models.CharField(max_length=500, default="", blank=True)
    desc = models.CharField(max_length=500, default="", blank=True)
    summary = models.CharField(max_length=500, default="", blank=True)

serializers.py

class DocumentListingField(serializers.RelatedField):
    def to_representation(self, instance):
        return model_to_dict(instance.document)

class MySourceSerializer(serializers.ModelSerializer):
    Document = DocumentListingField(many=False, read_only=True)

    class Meta:
        model = MySource
        fields = ("id", "url", "title", "publisher", "desc", "summary", "Document")

    def create(self, validated_data):
        # documentId = validated_data.pop("documentId")
        source = MySource.objects.create(
            document=Document.objects.get(id="J9DY2pE"), **validated_data
        )
        print(validated_data)
        source.save()
        return source


class DocumentSerializer(serializers.ModelSerializer):
    id = HashidSerializerCharField(source_field="documents.Document.id", read_only=True)
    question_blocks = QuestionBlockSerializer(many=True)
    outline_blocks = OutlineBlockSerializer(many=True)
    # TODO: disabling mysource until user foreign key is resolved
    mysource = MySourceSerializer(many=True)
    user = serializers.PrimaryKeyRelatedField(
        read_only=True, default=serializers.CurrentUserDefault()
    )

    class Meta:
        model = Document
        fields = "__all__"

    def create(self, validated_data):
        print(validated_data)
        question_blocks = validated_data.pop("question_blocks")
        outline_blocks = validated_data.pop("outline_blocks")
        document = Document.objects.create(**validated_data)
        for qBlock in question_blocks:
            QuestionBlock.objects.create(document=document, **qBlock)
        for oBlock in outline_blocks:
            OutlineBlock.objects.create(document=document, **oBlock)
        document.save()
        return document

Here I have two models: Document and MySource, where MySource has Document as its foreign key field. To summarize the relationship, Document is initialized with an empty array of MySource objects, where a user can later create a new MySource object.

I am trying to figure out a way to create a Document object with the following POST requests with mysource field set either optional or empty in the beginning.

POST REQUEST
{
  "title": "Untitled",
  "templateId": 30,
  "question_blocks": [],
  "outline_blocks": [],
}

This will give the error message: "mysource field is required"

POST REQUEST
{
  "title": "Untitled",
  "templateId": 30,
  "question_blocks": [],
  "outline_blocks": [],
  "mysource": []
}

This will give the error message: Direct assignment to the reverse side of a related set is prohibited. Use addresses.set() instead

models.py

class Document(models.Model):
    id = HashidAutoField(primary_key=True)
    # TODO: blank, null to False
    user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
    title = models.CharField(max_length=100, default="Untitled")
    template = models.CharField(max_length=100, default="")
    editorState = models.JSONField(default=[])
    updated = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

class MySource(models.Model):
    id = models.AutoField(primary_key=True)
    document = models.ForeignKey(
        Document,
        related_name="mysource",
        on_delete=models.CASCADE,
        null=True,
        blank=True,
    )
    documentId = models.CharField(max_length=50, default="", blank=True)
    url = models.CharField(max_length=500, default="", blank=True)
    title = models.CharField(max_length=500, default="", blank=True)
    publisher = models.CharField(max_length=500, default="", blank=True)
    desc = models.CharField(max_length=500, default="", blank=True)
    summary = models.CharField(max_length=500, default="", blank=True)

serializers.py

class DocumentListingField(serializers.RelatedField):
    def to_representation(self, instance):
        return model_to_dict(instance.document)

class MySourceSerializer(serializers.ModelSerializer):
    Document = DocumentListingField(many=False, read_only=True)

    class Meta:
        model = MySource
        fields = ("id", "url", "title", "publisher", "desc", "summary", "Document")

    def create(self, validated_data):
        # documentId = validated_data.pop("documentId")
        source = MySource.objects.create(
            document=Document.objects.get(id="J9DY2pE"), **validated_data
        )
        print(validated_data)
        source.save()
        return source


class DocumentSerializer(serializers.ModelSerializer):
    id = HashidSerializerCharField(source_field="documents.Document.id", read_only=True)
    question_blocks = QuestionBlockSerializer(many=True)
    outline_blocks = OutlineBlockSerializer(many=True)
    # TODO: disabling mysource until user foreign key is resolved
    mysource = MySourceSerializer(many=True)
    user = serializers.PrimaryKeyRelatedField(
        read_only=True, default=serializers.CurrentUserDefault()
    )

    class Meta:
        model = Document
        fields = "__all__"

    def create(self, validated_data):
        print(validated_data)
        question_blocks = validated_data.pop("question_blocks")
        outline_blocks = validated_data.pop("outline_blocks")
        document = Document.objects.create(**validated_data)
        for qBlock in question_blocks:
            QuestionBlock.objects.create(document=document, **qBlock)
        for oBlock in outline_blocks:
            OutlineBlock.objects.create(document=document, **oBlock)
        document.save()
        return document

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

撩发小公举 2025-02-11 11:42:15

我认为您需要将read_only = true属性添加到mySource字段中。

class DocumentSerializer(serializers.ModelSerializer):
    ...
    mysource = MySourceSerializer(many=True, read_only=True)
    ...

I think you need to add read_only=True attribute into the mysource field.

class DocumentSerializer(serializers.ModelSerializer):
    ...
    mysource = MySourceSerializer(many=True, read_only=True)
    ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文