2017-09-29 96 views
0

TL; DR:如何使用formset保存/验证具有唯一属性的多个对象?使用Django formset保存具有唯一属性的多个对象

比方说,我有一个Machine其中有多个Setting(见下面的模型)。这些设置应该在机器内具有唯一的顺序。然而

unique_together = (('order', 'machine'),) 

,我使用的是内联表单集更新所有SettingMachine的:这可以通过在MetaSetting模型的定义unique_together属性来完成。假设我的表单中有以下信息:

  • 设置1:machine = 1; order = 1
  • 设置2:machine = 1;顺序= 2

如果我要切换的两个Setting s量级:

  • 设置1:机器= 1; order = 2
  • 设置2:machine = 1;为了= 1

,并使用下面的代码保存表单:

self.object = machine_form.save() 
settings = setting_formset.save(commit=False) 
for setting in settings: 
    setting.machine = self.object 
    setting.save() 

然后我得到的唯一约束错误,因为我想保存顺序设定1 = 2,而是设置2仍然有这个顺序。我似乎无法找到这个问题的干净解决方案。我想保持unique_together约束,以确保我的数据的正确性。我知道如何使用Javascript在前端解决这个问题,但我想在我的模型/表单中进行检查。在formset行上循环似乎是可能的,但丑陋?

class Machine(models.Model): 
    name = models.CharField(max_length=255) 

class Setting(models.Model): 
    name = models.CharField(max_length=255) 
    machine = models.ForeignKey(Machine, on_delete=models.CASCADE) 
    order = models.PositiveSmallIntegerField() 

回答

0

似乎无法限制数据库级别的顺序。我不是说这不可能,但我不知道如何。

现在,我在我的formset中添加了一个检查。如果有人遇到类似问题,我会将其留在这里。

class BaseSettingFormSet(BaseInlineFormSet): 
    '''FormSet to update the order of Settings in a Machine''' 

    def clean(self): 
     '''Checks if there are no two Settings with the same order.''' 
     if any(self.errors): 
      return 
     orders = [] 
     for form in self.forms: 
      if form.cleaned_data: 
       order = form.cleaned_data['order'] 
       if order in orders: 
        form.add_error('order', _('The order of each setting must be unique')) 
       else: 
        orders.append(order) 
相关问题