Django REST Framework:从POSTed数据创建相关模型

时间:2018-06-15 14:30:35

标签: django django-models django-rest-framework

使用以下型号:

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.

如何创建资源并将其附加到现有的相关对象?

2 个答案:

答案 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