2017-12-18 85 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方面,但仍将在数据库级别作为外键处理。

相关问题