【问题标题】:Django - preventing duplicate recordsDjango - 防止重复记录
【发布时间】:2013-04-06 20:17:17
【问题描述】:

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

现在,我不能简单地将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 也是这个模型的一个字段——可能设计不佳,但它确实有效。

【问题讨论】:

    标签: django django-validation


    【解决方案1】:

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

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

    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
    

    【讨论】:

    • 我发现如果我想编辑已经创建的笔记记录,这实际上会失败。这将始终验证当前年份已经存在注释,并且不允许编辑。我该如何解决?
    • 编辑已有笔记记录时,给出year+systemId,不需要验证。您可以通过在 clean 方法中添加条件来参数化此表单并重用它,或者将不同的表单用于两种不同的目的(添加新的与编辑现有的)
    • 对于 Django 1.7+,首选方法是使用新的form.add_error
    猜你喜欢
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 1970-01-01
    • 2012-10-17
    • 2016-07-10
    • 2015-12-04
    • 2015-04-24
    • 1970-01-01
    相关资源
    最近更新 更多