Django - 防止重复记录

时间:2013-04-06 20:17:17

标签: django django-validation

我的数据库中有一个客户记录列表。每年,我们为每个客户生成一份工单。然后,对于每个工单记录,用户应该能够创建特定于工单的注释。但是,并非所有工作单都需要注释,只有一些。

现在,我不能简单地将note字段添加到工单中,因为有时我们需要在工作订单生成之前创建注释。有时,此注释特定于工作订单,该工作订单将在2 - 3年内不会发生。因此,票据和工单必须是独立的,尽管它们在存在时会相互“找到”。

好的,所以情况就是这样。我希望用户能够填写一个非常简单的note表单,其中有两个字段:noteYearnote。因此,他们所做的只是选择一年,然后写下笔记。踢球者是用户不应该为同一客户创建同一年的两个笔记。

我正在尝试通过确保该客户的那一年没有该笔记来验证该笔记。我假设这将通过表单中的自定义is_valid方法实现,但我无法弄清楚如何去做。

这是我到目前为止所尝试的(注意我知道这是错的,它不起作用,但这是我迄今为止的尝试):

请注意systemID是我的客户记录

我的模特:

class su_note(models.Model):
    YEAR_CHOICES = (
        ('2013', 2013),        
        ('2014', 2014),        
        ('2015', 2015),        
        ('2016', 2016),        
        ('2017', 2017),        
        ('2018', 2018),        
        ('2019', 2019),        
        ('2020', 2020),        
        ('2021', 2021),        
        ('2022', 2022),        
        ('2023', 2023),        
    )
    noteYear = models.CharField(choices = YEAR_CHOICES, max_length = 4, verbose_name = 'Relevant Year')
    systemID = models.ForeignKey(System, verbose_name = 'System ID')
    note = models.TextField(verbose_name = "Note")

    def __unicode__(self):
        return u'%s | %s | %s' % (self.systemID.systemID, self.noteYear, self.noteType)

我的表格:

class SU_Note_Form(ModelForm):
    class Meta:
        model = su_note
        fields = ('noteYear', 'noteType', 'note')
    def is_valid(self):
        valid = super (SU_Note_Form, self).is_valid()

        #If it is not valid, we're done -- send it back to the user to correct errors
        if not valid:
            return valid

        # now to check that there is only one record of SU for the system
        sysID = self.cleaned_data['systemID']
        sysID = sysID.systemID
        snotes = su_note.objects.filter(noteYear = self.cleaned_data['noteYear'])
        for s in snotes:
            if s.systemID == self.systemID:
                self._errors['Validation_Error'] = 'There is already a startup note for this year'
                return False
        return True

编辑 - 这是我的解决方案(感谢janos向我发送正确的方向)

我的最终表格如下:

class SU_Note_Form(ModelForm):
    class Meta:
        model = su_note
        fields = ('systemID', 'noteYear', 'noteType', 'note')
    def clean(self):
        cleaned_data = super(SU_Note_Form, self).clean()
        sysID = cleaned_data['systemID']
        sysID = sysID.systemID
        try:
            s = su_note.objects.get(noteYear = cleaned_data['noteYear'], systemID__systemID = sysID)
            print(s)
            self.errors['noteYear'] = "There is already a note for this year."
        except:
            pass
        return cleaned_data        

对于其他任何查看此代码的人来说,唯一令人困惑的部分是具有以下内容的行:sysID = sysID.systemIDsystemID实际上是另一个模型的一个字段 - 即使systemID也是这个模型的一个字段 - 可能是糟糕的设计,但它有效。

1 个答案:

答案 0 :(得分:4)

在Django文档中查看此页面: https://docs.djangoproject.com/en/dev/ref/forms/validation/

由于验证逻辑依赖于两个字段(年份和systemID),因此您需要使用表单上的自定义清理方法来实现此目的,例如:

def clean(self):
    cleaned_data = super(SU_Note_Form, self).clean()
    sysID = cleaned_data['systemID']
    sysID = sysID.systemID
    try:
        su_note.objects.get(noteYear=cleaned_data['noteYear'], systemID=systemID)
        raise forms.ValidationError('There is already a startup note for this year')
    except su_note.DoesNotExist:
        pass

    # Always return the full collection of cleaned data.
    return cleaned_data