【发布时间】:2018-09-29 00:14:46
【问题描述】:
我有一个票模型,以及它的票序列化器。票证模型有一个bought 和一个booked_at 字段。还有一个 unique_together 属性用于表演和座位。
class Ticket(models.Model):
show = models.ForeignKey(Show, on_delete=models.CASCADE)
seat = models.ForeignKey(Seat, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
booked_at = models.DateTimeField(default=timezone.now)
bought = models.BooleanField(default=False)
class Meta:
unique_together = ('show', 'seat')
- 在门票序列化程序上,验证序列化程序会检查是否有任何门票具有所需座位并显示
- 如果有票,则检查票是否已购买。
- 如果是购买的,则会引发错误。
- 如果未购买,请检查是否在 5 分钟内预订了机票。
- 如果在 5 分钟内预订,则引发错误。
- 如果预订时间超过5分钟,则删除旧票并返回有效。
- 如果有票,则检查票是否已购买。
- 如果没有票则返回有效
TicketSerializer:
class TicketSerializer(serializers.Serializer):
seat = serializers.PrimaryKeyRelatedField(queryset=Seat.objects.all())
show = serializers.PrimaryKeyRelatedField(queryset=Show.objects.all())
user = serializers.PrimaryKeyRelatedField(queryset=User.objects.all())
bought = serializers.BooleanField(default=False)
def validate(self, attrs):
if attrs['seat']:
try:
ticket = Ticket.objects.get(show=attrs['show'], seat=seat)
if not ticket.bought:
if ticket.booked_at < timezone.now() - datetime.timedelta(minutes=5):
# ticket booked crossed the deadline
ticket.delete()
return attrs
else:
# ticket in 5 mins range
raise serializers.ValidationError("Ticket with same show and seat exists.")
else:
raise serializers.ValidationError("Ticket with same show and seat exists.")
except Ticket.DoesNotExist:
return attrs
else:
raise serializers.ValidationError("No seat value provided.")
在视图中,我使用@transaction.atomic() 确保仅在所有票证都有效时创建票证,或者如果无效则不创建任何票证。
@transaction.atomic()
@list_route(
methods=['POST'],
permission_classes=[IsAuthenticated],
url_path='book-tickets-by-show/(?P<show_id>[0-9]+)'
)
def book_tickets_by_show(self, request, show_id=None):
try:
show = Show.objects.get(id=show_id)
user = request.user
...
...
data_list = [...]
with transaction.atomic():
try:
serializer = TicketSerializer(data=data_list, many=True)
if serializer.is_valid():
serializer.save()
....
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except (Seat.DoesNotExist, ValueError, ConnectionError) as e:
return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST)
except (Show.DoesNotExist, IntegrityError) as e:
return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST)
我想知道的是,它是否有助于防止为同一个座位创建票证而调用多个请求?
假设,用户 A 想要预订座位 5,6 的机票。用户 B 想预订 3,6 号座位的票,另一个用户 C 想预订 2,3,4,5,6 号座位的票。
上述方法是否会阻止为所有用户预订各自座位的门票,并且只为一个用户创建门票(可能是第一个交易的用户)?或者如果有更好的方法,请告诉我如何做。我希望我很清楚。如果没有请询问。
【问题讨论】: