Django -父记录创建后将数据插入子表

xt0899hw  于 2023-04-07  发布在  Go
关注(0)|答案(1)|浏览(92)

我正在使用Django REST Framework,在将数据插入子表时遇到了一个问题。有两个名为CardContactName的模型,它们具有以下字段。Card通过外键字段名cardContactName有关系。
models.py

class Card(models.Model):
    image = models.ImageField(upload_to='images', max_length=255, null=True, blank=True)
    filename = models.CharField(max_length=255, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.filename

class ContactName(models.Model):
    first_name = models.CharField(max_length=255, null=True, blank=True)
    last_name = models.CharField(max_length=255, null=True, blank=True)
    confidence = models.FloatField(default=0)
    card = models.ForeignKey(Card, on_delete=models.CASCADE, related_name='contact_name')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.first_name

serializers.py文件:

class ContactNameSerializer(serializers.ModelSerializer):
    class Meta:
        model = ContactName
        fields = ['id', 'first_name', 'last_name', 'confidence', 'card', 'created_at', 'updated_at']

class CardSerializer(serializers.ModelSerializer):
    contact_name = ContactNameSerializer(many=True, read_only=True)
    class Meta:
        model = Card
        fields = ['id', 'image', 'filename', 'contact_name', 'created_at', 'updated_at']

ViewSet中,一旦创建了卡记录,我还想将以下ContactNameJSON数据添加到子表中,将reference (card_id) 设置为该卡的id,并在响应中返回新添加的记录。
e.g.

[
  {
    "first_name": "John",
    "last_name": "Doe",
    "confidence": 0.9
  },
  {
    "first_name": "Doe",
    "last_name": "John",
    "confidence": 0.5
  }
]

views.py

class CardViewSet(viewsets.ModelViewSet):
    parser_classes = (MultiPartParser, FormParser)

    queryset = Card.objects.all()
    serializer_class = CardSerializer

    def create(self, request):
        cards_serializer = CardSerializer(data=request.data)
        if cards_serializer.is_valid():
            cards_serializer.save()

            # insert the record into the child table and set the reference (card_id) as an id
            json = [
                {
                    "first_name": "John",
                    "last_name": "Doe",
                    "confidence": 0.9
                },
                {
                    "first_name": "Doe",
                    "last_name": "John",
                    "confidence": 0.5
                }
            ]

            return Response(cards_serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(cards_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

我真的很感激你的帮助。最后的回复会是这样的:

{
  "id": 10,
  "image": "/media/abc.jpg",
  "filename": "abc.jpg",
  "contact_names": [
    {
      "id": 1,
      "first_name": "John",
      "last_name": "Doe",
      "confidence": 0.9,
      "card_id": 10
    },
    {
      "id": 2,
      "first_name": "Doe",
      "last_name": "John",
      "confidence": 0.5,
      "card_id": 10
    }
  ]
}
wvt8vs2t

wvt8vs2t1#

基本上,你可以通过Including extra context和覆盖create方法将这些数据传递给你的serializer,就像你在代码中所做的那样:
views.py

class CardViewSet(viewsets.ModelViewSet):
    parser_classes = (MultiPartParser, FormParser)

    queryset = Card.objects.all()
    serializer_class = CardSerializer

    def create(self, request):
        json = [
            {
                "first_name": "John",
                "last_name": "Doe",
                "confidence": 0.9
            },
            {
                "first_name": "Doe",
                "last_name": "John",
                "confidence": 0.5
            }
        ]
        
        serializer = CardSerializer(data=request.data, context={'contacts': json})
        if serializer.is_valid(raise_exception=True):
            serializer.save()

            return Response(serializer.data, status=status.HTTP_201_CREATED)

另外,覆盖CardSerializer上的create方法,首先使用验证的数据创建示例,然后使用extra context data创建ContactName对象并将它们分配给新的Card示例:
serializers.py

class ContactNameSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.ContactName
        fields = ['id', 'first_name', 'last_name', 'confidence', 'card']

class CardSerializer(serializers.ModelSerializer):
    contact_name = ContactNameSerializer(many=True, read_only=True)
    class Meta:
        model = models.Card
        fields = ['id', 'image', 'filename', 'contact_name', 'created_at', 'updated_at']

    def create(self, validated_data):
        instance = models.Card.objects.create(**validated_data)
        contacts = self.context.get('contacts', None)
        for contact in contacts:
            models.ContactName.objects.create(**contact, card=instance)
            
        return instance

注意事项:

如果您希望在响应数据上使用card_id而不是card,请更改字段名称(并更新序列化器字段):

class ContactName(models.Model):
    ...
    card_id = models.ForeignKey(Card...)
    ...

或者,您可以覆盖.to_representation,删除key:pair并重新插入新的键值。
另外,我会将此关系更改为多对多,以避免数据库中的ContactName重复。

相关问题