Django 模型避免重复

Posted

技术标签:

【中文标题】Django 模型避免重复【英文标题】:Django models avoid duplicates 【发布时间】:2011-03-04 10:29:40 【问题描述】:

在模型中:

class Getdata(models.Model):
    title = models.CharField(max_length=255)
    state = models.CharField(max_length=2, choices=STATE, default="0")
    name = models.ForeignKey(School)
    created_by = models.ForeignKey(profile)

    def __unicode__(self):
        return self.id()

在模板中:

<form>
    <input type="submit" value="save the data" />
</form> 

如果用户点击保存按钮,上面的数据保存在表格中,如何避免重复,即如果用户再次点击同一个提交按钮,不应该有相同值的另一个条目。还是必须在视图中处理?

【问题讨论】:

【参考方案1】:

我认为注入 Jquery/JS 代码来隐藏保存按钮是个好主意。

创建一个如下所示的 custom_validate.js 文件并将其放在目录 static(静态文件目录)中

if (!$) 
    $ = django.jQuery;


$( document ).ready(function() 
    $("[name=_save]").click(function() 
       $("[name=_save]").css("visibility", "hidden");
    );
);

在 admin.py 中,添加以下代码。

class CustomDataForm(forms.ModelForm):

    class Meta:
        model = GetData

class GetDataAdmin(admin.ModelAdmin):
    # ....
    .....
    form = CustomDataForm

    class Media:
        js = ('/static/custom_validate.js', )

【讨论】:

【参考方案2】:

unique_together 也建议是最好的方法,但如果这不适合您的需要,您可以在表单的 clean 方法中处理它。例如

def clean(self):
   try:
      Getdata.objects.get(title=self.cleaned_data['title'], 
                          state=self.cleaned_data['state'],
                          name=self.cleaned_data['name'],
                          created_by=self.cleaned_data['created_by'] )
      #if we get this far, we have an exact match for this form's data
      raise forms.ValidationError("Exists already!")
   except Getdata.DoesNotExist:
      #because we didn't get a match
      pass

   return self.cleaned_data

【讨论】:

我还看到,对于多次提交的情况,人们使用 javascript 在单击提交按钮并提交表单时禁用它。最好的解决方案可能是所有这些的组合。 在我的代码中我暂时做了同样的事情..但这与其他人不一致..所以我必须知道这一点..下次我可以使用正确的代码而不是黑客..【参考方案3】:

如果单个字段需要唯一,则只需添加unique=True

class Getdata(models.Model):
    title = models.CharField(max_length=255, unique=True)
    state = models.CharField(max_length=2, choices=STATE, default="0")
    name = models.ForeignKey(School)
    created_by = models.ForeignKey(profile)

如果希望字段组合唯一,则需要unique_together:

class Getdata(models.Model):
    title = models.CharField(max_length=255)
    state = models.CharField(max_length=2, choices=STATE, default="0")
    name = models.ForeignKey(School)
    created_by = models.ForeignKey(profile)
    class Meta:
        unique_together = ["title", "state", "name"]

【讨论】:

另外,当 getdata 在视图中调用第二个示例时,默认情况下这将返回“title”、“state”和“name”是吗? 当您在视图中引用 Getdata 对象时,您将获得一个 Getdata 对象及其所有字段。

以上是关于Django 模型避免重复的主要内容,如果未能解决你的问题,请参考以下文章

Django/Python DRY:使用 Q 对象和模型属性时如何避免重复代码

如何避免 Django Forms 和 Django Rest Framework Serializers 中的代码重复?

Django表单在单个HTML中多次使用,避免重复的id

避免在 Django 模板 HTML 表中出现重复的“if 条件”

Django模型基于两个变量防止重复[重复]

Django 上传:丢弃上传的重复文件,使用现有文件(基于 md5 的检查)