2017-12-18 195 views
0

例如一個表不能外鍵給別人,除了一個表

class Room(models.Model): 
    visitor = models.ForeignKey(Visitor) 
    number = models.PositiveIntegerField() 
    capacity = models.ForeignKey(Capacity, on_delete=models.PROTECT) 
    floor = models.ForeignKey(Floor, on_delete=models.PROTECT) 
    price = models.PositiveIntegerField() 
    is_premium = models.BooleanField(default=False) 
    is_vip = models.BooleanField(default=False) 
    expiry_date = models.DateTimeField() 

    class Meta: 
     unique_together = ('') 

    def __str__(self): 
     return '№{0}'.format(self.number) 


class Reserved(models.Model): 
    room = models.ForeignKey(Room) 
    begin_date = models.DateTimeField() 

    def __str__(self): 
     return 'Reserved Room {0}'.format(self.room) 

class Busy(models.Model): 
    room = models.ForeignKey(Room) 

表間無法連接到表保留,並在同一時間忙。房間應保留或忙碌。有沒有辦法對此進行驗證? 我試圖用unique_together但是如果表中的字段

感謝

回答

0

沒有辦法在數據庫級別,也不是簡單的方法來做到這一點在Django級別執行此操作。對於你的結構,你應該在創建(或修改)BusyReserved之前添加一些驗證。喜歡的東西:

class Busy(models.Model): 
    room = models.ForeignKey(Room) 

    def __save__(self, *args, **kwargs): 
     if Reserved.object.filter(room=self.room).exists(): 
      raise RuntimeError('Trying to make a reserved room busy.') 
     super(Busy, self).__save__(*args, **kwargs) 

如果要創建BusyReserved對象同時它受到的競爭條件。我建議將房間狀態移入Room模型本身並添加一些輔助函數(類似旁邊的room_manager.py)以更改其狀態並確保以一致的方式創建/修改相關模型。

0

確保在數據庫級別你有一個單一的「身份」在給定的時間,一個房間是有你的關係,反過來想,唯一的方法 - 用Room有一個外鍵上的任何代表狀態。爲了完成這個工作,你需要使用某種形式的模型繼承或者django的「通用」關係(它可能有時候很方便但實際上不適合SQL)。

這是一個使用「模型繼承」(這實際上不是繼承的話)的最簡單形式的例子:

class Status(models.Model): 
    BUSY = 1 
    RESERVED = 2 
    TYPES = (
     (BUSY,"busy"), 
     (RESERVED,"reserved") 
    ) 
    type = models.CharField("Status type", max_length=10, choices=TYPES) 
    # only used for reservations 
    begin_date = models.DateTimeField(null=True, blank=True) 

    def save(self, *args, **kw): 
     # TODO : this should belong to `full_clean()`, 
     # cf the FineManual model's validation 
     if self.type == self.RESERVED and not self.begin_date: 
      raise ValueError("RESERVED statuses need a begin_date") 
     super(Status, self).save(*args, **kw) 




class Room(models.Model): 
    status = models.ForeignKey(Status) 

注意,這允許相同的狀態,以用於在多個房間同時,這也可能是一個問題。使用OneToOneField字段可能有助於Django方面,但仍將在數據庫級別作爲外鍵處理。

相關問題