我使用Django REST Framework
,在向子表插入数据时遇到问题。Card
和ContactName
两种模型具有以下字段:Card
通过外键字段名称card
与ContactName
建立关系。
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
file:
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
中,一旦卡记录被创建,我还想将以下ContactName
JSON
数据添加到子表中,设置引用(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
重复。