2012-07-11 49 views
1

我希望ForeignKey的每个实例具有不同的默认值,具体取决于它在父模型中的属性。做的时候如何为外键中的特定字段指定默认的外地字段值?

class Day(models.Model): 
    date = models.DateField(unique=True) 
    manager_shift = models.ForeignKey('Shift') # Shift.shift_type should be "M" 
    lead_shift = models.ForeignKey('Shift') # Shift.shift_type should be "L" 
    early_day_shift = models.ForeignKey('Shift') # Shift.shift_type should be "ED" 
    late_day_shift = models.ForeignKey('Shift') # Shift.shift_type should be "LD" 
    swing_shift = models.ForeignKey('Shift') # Shift.shift_type should be "SW" 
    early_evening_shift = models.ForeignKey('Shift') # Shift.shift_type should be "EM" 
    late_evening_shift = models.ForeignKey('Shift') # Shift.shift_type should be "LM" 

class Shift(models.Model): 
    user = models.ForeignKey('User', limit_choices_to={'is_staff': True}, blank=False) 
    shift_type = models.CharField(max_length=2, choices=SHIFT_TYPE_CHOICES, blank=False) 

SHIFT_TYPE_CHOICES = { 
    ('M', 'Manager'), 
    ('L', 'Lead'), 
    ('ED', 'Early Day'), 
    ('LD', 'Early Day'), 
    ('SW', 'Swing'), 
    ('EM', 'Early Evening'), 
    ('LM', 'Late Evening'), 
} 

在这种情况下,

所以:

的插图可能使这更清楚

Day.manager_shift = Shift() 

Day.manager_shift.shift_type应该是 “M” 自动

回答

1

我不相信有这样做的内置方式,也不应该有b即如果你做了,会发生什么:

>>> my_shift = Shift() 
>>> Day.manager_shift = my_shift 
>>> Day.lead_shift = my_shift 
>>> my_shift.shift_type 
??? 

一个更好的选择将是压倒一切的Daysave方法检查所保存的对象和各个领域:1)如果没有shift_type,加上正确的; b)如果出现换班时间,但出现错误,提出错误(不是最干净的解决方案,但我不知道更好的)。

更新:我只是read编辑:和罗汉也指出),您可以给一个默认值到ForeignKey,但你应该在一个函数的形式,这样做的:

def default_type(type): 
    temp = [type] # Necessary because Python can't handle closures properly sometimes 
    def closure(): 
     return Shift.objects.get(shift_type=temp[0]) 
    return closure 

class Day(models.Model): 
    date = models.DateField(unique=True) 
    manager_shift = models.ForeignKey('Shift', default=default_type('M')) 
+0

我明白你的意思,但以同样的方式你可以为未指定值的模型的字段指定默认值,对于我来说,你可以为正在创建新实例的字段指定默认的外部字段值。 – Ben174 2012-07-11 05:18:10

+0

是的,但你会用什么作为价值?唯一对我有意义的是使用另一个模型的主键(因为这是唯一可以唯一标识该模型中的一行)。 – mgibsonbr 2012-07-11 05:21:05

1

你可以有默认值作为可调用的,所以你可以这样做:

def get_m_shift(): 
    return Shift.objects.get(shitf_type='M') 

    class Day(models.Model): 
     date = models.DateField(unique=True) 
     manager_shift = models.ForeignKey('Shift', default=get_m_shift) 

我想你必须编写函数来获取每个班次类型。我不确定默认的可调用参数。

+0

尽管您无法传递参数,但您可以让其他函数返回可调用对象(即创建一个闭包)。以我的答案为例。 – mgibsonbr 2012-07-11 05:18:52

+0

这是不是我想要的。 Shift对象尚不存在。我希望创建的新Shift对象具有该“M”值(如果它们被分配给manager_shift属性)。我期望看到的代码是这样的:manager_shift = models.ForeignKey('Shift',shift.shift_type =“M”) – Ben174 2012-07-11 05:25:53

+0

@ Ben174如果你想创建它,你需要获得_User_实例来创建_Shift_,是可用的吗? – Rohan 2012-07-11 05:29:33

1

为什么你有一个单独的'日'模型?

SHIFT_TYPE_CHOICES = { 
    ('M', 'Manager'), 
    ('L', 'Lead'), 
    ('ED', 'Early Day'), 
    ('LD', 'Early Day'), 
    ('SW', 'Swing'), 
    ('EM', 'Early Evening'), 
    ('LM', 'Late Evening'), 
} 

class Shift(models.Model): 
    user = models.ForeignKey('User', 
          limit_choices_to={'is_staff': True}, 
          blank=False) 
    shift_type = models.CharField(max_length=2, 
            choices=SHIFT_TYPE_CHOICES, 
            blank=False) 
    shift_date = models.DateField() 

    class Meta: 
     unique_together = (('shift_date','shift_user','shift_type'),) 

这样可以防止同一用户在同一日期发生重复的班次,只有一种班次类型和用户的组合。您可以根据自己的需求进行调整。因此,如果您需要在同一日期多次轮班,请删除shift_datedocumentation for unique_together解释了这是如何工作的。

现在,找出谁是在特定的一天店长:

for s in Shift.objects.filter(shift_type='M', 
           shift_date=datetime.datetime.today()): 
    print s.user 

或者打印天整个阵容:

for s in Shift.objects.filter(shift_date=datetime.datetime.today()): 
    print "%s: %s\n" % (s.get_shift_type_display(),s.user) 
+0

我同意Day对象完全没有意义。但是这个对象模型已经在视图中被大量使用。这将需要一些重大的重构来删除它。我继承了这个项目。 – Ben174 2012-07-11 05:40:35