Check whether an object with its unique together fields exist to create or delete before saving

时间:2017-07-01 19:24:47

标签: django django-rest-framework

Please consider this Ticket model, where its two fields (show and seat) should be unique together. Also it has a boolean field (paid) to indicate whether the ticket is paid or not.

model:

class Ticket(models.Model):
    show = models.ForeignKey(Show)
    seat = models.ForeignKey(Seat)
    user = models.ForeignKey(User)
    paid = models.BooleanField(default=False)

    class Meta:
        unique_together = ('show', 'seat')

This is an example of the client side data

[
    {u'seat': 6, u'user': 3, u'show': 2}, 
    {u'seat': 7, u'user': 3, u'show': 2}
]

And the views:

def buy_ticket(request):
    serialized = TicketSerializer(data=request.data, many=True)
    if serialized.is_valid():
        serialized.save()
        return Response(serialized.data, status=status.HTTP_201_CREATED)
    return Response(serialized._errors, status=status.HTTP_400_BAD_REQUEST)

What I would like to do is check whether there is any Ticket with the provided data (seat and show). If there is no such Ticket then create a new one. Or else, if there is a Ticket, then check if that ticket has been paid. If its not paid then delete that ticket and create a new one with the new data, or else raise an error.

I tried doing this way in the serializer, but I am still getting a uniqueness error:

class TicketSerializer(serializers.ModelSerializer):
    class Meta:
        model = Ticket
        fields = '__all__'

    def validate(self, data):
        try:
            ticket = Ticket.objects.get(seat=data['seat'], show=data['show'])
            if not ticket.paid:
                ticket.delete()
                return data
        except Ticket.DoesNotExist:
            return data

2 个答案:

答案 0 :(得分:0)

使用get_or_create

ticket, created = Ticket.objects.get_or_create(seat=data['seat'], show=data['show'], user=data['user'])
if not created and not ticket.paid:
    ticket.delete()
return data

您需要user,因为它是必填字段。

答案 1 :(得分:0)

根据whp的建议,修改The_Cthulhu_Kid的答案,试试这个

from django.db import transaction

class TicketSerializer(serializers.ModelSerializer):
    class Meta:
        model = Ticket
        fields = '__all__'

    def validate(self, data):

        with transaction.atomic():
            ticket, created = Ticket.objects.get_or_create(seat=data['seat'], show=data['show'], user=data['user'])
            if not created and not ticket.paid:
                ticket.delete()
            else:
                raise ValidationError("Your error here")
        return data