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