2017-07-01 101 views
0

請考慮此票證模型,其中兩個字段(showseat)應該唯一。它還有一個布爾字段(paid)來表明票是否支付。檢查是否存在具有唯一字段的對象,以在保存之前創建或刪除

型號:

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') 

這是客戶端的數據

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

而且意見的例子:

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) 

我想要做的是檢查是否有是提供數據的任何票(seatshow)。如果沒有這樣的票證,則創建一個新票據。否則,如果有票,則檢查該票是否已支付。如果未付款,則刪除該憑單並用新數據創建一個新憑單,否則會引發錯誤。

我試圖在串行這樣的方式,但我仍然得到一個唯一的錯誤:

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

可能不是你的唯一錯誤的根源,但我認爲你在那裏有一個競爭條件。你需要確保它被封裝在一個事務中,或者實現某種在你的delete()和create()調用之間持續存在的鎖定。 – whp

+0

@whp我很抱歉,我沒有得到你。你能否再解釋一下。謝謝。 – Aamu

+1

不要在序列化程序中執行此操作。這是模型管理員或視圖的任務。串行器應該將模型轉換成json,而不是做其他任何事情。 – Melvyn

回答

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,因爲它是一個必填字段。

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 
+0

我應該在哪裏調用上述交易代碼? – Aamu

+0

我想你的表單驗證。在你的'validate()'方法中。我應該編輯我的答案,包括其餘的。 – zaidfazil

相關問題