使用以下型号:
class Ticket(models.Model):
[some irrelevant fields]
class TicketComment(models.Model):
text = models.TextField()
creator = models.CharField(max_length=255)
ticket = models.ForeignKey(Ticket, models.CASCADE, related_name='comments')
我创建了以下序列化程序:
class TicketSerializer(serializers.ModelSerializer):
[irrelevant]
class TicketCommentSerializer(serializers.ModelSerializer):
class Meta:
model = TicketComment
fields = '__all__'
def create(self, validated_data):
return TicketComment.objects.create(**validated_data)
观点:
class TicketCommentView(APIView):
lookup_url_kwarg = 'ticket_id'
def post(self, request, ticket_id):
data = request.data
data['creator'] = 'joe'
try:
data['ticket'] = Ticket.objects.get(pk=ticket_id)
except Ticket.DoesNotExist:
raise NotFound('Ticket {} does not exist.'.format(ticket_id))
serializer = TicketCommentSerializer(data=data)
serializer.is_valid(raise_exception=True)
comment = serializer.save()
return Response(comment, status=HTTP_201_CREATED)
网址格式:
urlpatterns = [
path('ticket/<int:ticket_id>/comment', TicketCommentView.as_view()),
]
但是,在尝试POST数据{"text": "test"}
时,它会失败并显示:
"ticket": ["Incorrect type. Expected pk value, received Ticket."]
如果我更改视图以传递ticket_id
整数而不是票证实例,则会抱怨重复键:
django.db.utils.IntegrityError: duplicate key value violates unique constraint "ticketcomment_pkey"
DETAIL: Key (id)=(41993) already exists.
如何创建资源并将其附加到现有的相关对象?
答案 0 :(得分:1)
不是将票证作为序列化数据传递,而是直接将其传递给序列化程序的保存方法(related part文档):
def post(self, request, ticket_id):
data = request.data
try:
ticket = Ticket.objects.get(pk=ticket_id)
except Ticket.DoesNotExist:
raise NotFound('Ticket {} does not exist.'.format(ticket_id))
serializer = TicketCommentSerializer(data=data)
serializer.is_valid(raise_exception=True)
comment = serializer.save(ticket=ticket, creator='joe')
return Response(comment, status=HTTP_201_CREATED)
在TicketCommentSerializer
中注意,您应该只留下文字字段:
class TicketCommentSerializer(serializers.ModelSerializer):
class Meta:
model = TicketComment
fields = ['text']
答案 1 :(得分:-1)
首先,您不应在序列化程序中包含id
,因为它主要是自动增量值。这就是为什么你得到Integrity Error
。