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



我使用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.pyfile:

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数据添加到子表中,设置引用(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
}
]
}

基本上你可以通过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重复。

相关内容

  • 没有找到相关文章

最新更新