在Django中保存表单数据之前进行重复检查

在Django中保存表单数据之前进行重复检查,django,forms,Django,Forms,我得到了如下表格: class CourseAddForm(forms.ModelForm): """Add a new course""" name = forms.CharField(label=_("Course Name"), max_length=100) description = forms.Textarea() course_no = forms.CharField(label=_("course Number"), max_length=15) #Att

我得到了如下表格:

class CourseAddForm(forms.ModelForm):
  """Add a new course"""
  name = forms.CharField(label=_("Course Name"), max_length=100)
  description = forms.Textarea()
  course_no = forms.CharField(label=_("course Number"), max_length=15)


  #Attach a form helper to this class
  helper = FormHelper()
  helper.form_id = "addcourse"
  helper.form_class = "course"

  #Add in a submit and reset button
  submit = Submit("Add", "Add New Record")
  helper.add_input(submit)
  reset = Reset("Reset", "Reset")
  helper.add_input(reset)

def clean(self):
  """ 
  Override the default clean method to check whether this course has been already inputted.
  """    
  cleaned_data = self.cleaned_data
  name = cleaned_data.get('name')
  hic = cleaned_data.get('course_no')

  try:
    course=Course.objects.get(name=name)
  except Course.DoesNotExist:
    course=None

  if course:
    msg = u"Course name: %s has already exist." % name
    self._errors['name'] = self.error_class([msg])
    del cleaned_data['name']
    return cleaned_data
  else:
    return self.cleaned_data

  class Meta:
    model = Course
@login_required
@csrf_protect
@never_cache
@custom_permission_required('records.change_course', 'course')
def edit_course(request,course_id):
  # See if the family exists:
try:
  course = Course.objects.get(id=course_id)
except Course.DoesNotExist:
  course = None

if course:
  if request.method == 'GET':
    form = CourseEditForm(instance=course)
    return render_to_response('records/add.html',
                            {'form': form},
                            context_instance=RequestContext(request)
                            )
  elif request.method == 'POST':
    form = CourseEditForm(request.POST, instance=course)
    if form.is_valid():
      form.save()
      return HttpResponseRedirect('/records/')
    # form is not valid: 
    else:
      error_message = "Please correct all values marked in red."
      return render_to_response('records/edit.html', 
                              {'form': form, 'error_message': error_message},
                              context_instance=RequestContext(request)
                              )      
else:
  error = "Course %s does not exist. Press the 'BACK' button on your browser." % (course)
  return HttpResponseRedirect(reverse('DigitalRecords.views.error', args=(error,)))
正如您所见,我重写了clean方法,以检查当用户试图添加该课程时,该课程是否已经存在于数据库中。这对我来说很好

但是,当我想为表单添加相同的检查以进行编辑时,出现了问题。因为它正在编辑,所以数据库中已经存在具有相同课程名称的记录。因此,如果课程名称已经存在,相同的检查将抛出错误。但是我需要检查重复,以避免用户将课程名称更新为另一个已经存在的课程名称

我正在考虑检查课程名称的值,看看它是否被更改。如果它已被更改,那么我可以执行与上面相同的检查。如果它没有被改变,我不需要做检查。但我不知道如何获取原始数据进行编辑

有人知道在Django怎么做吗

我的看法如下:

class CourseAddForm(forms.ModelForm):
  """Add a new course"""
  name = forms.CharField(label=_("Course Name"), max_length=100)
  description = forms.Textarea()
  course_no = forms.CharField(label=_("course Number"), max_length=15)


  #Attach a form helper to this class
  helper = FormHelper()
  helper.form_id = "addcourse"
  helper.form_class = "course"

  #Add in a submit and reset button
  submit = Submit("Add", "Add New Record")
  helper.add_input(submit)
  reset = Reset("Reset", "Reset")
  helper.add_input(reset)

def clean(self):
  """ 
  Override the default clean method to check whether this course has been already inputted.
  """    
  cleaned_data = self.cleaned_data
  name = cleaned_data.get('name')
  hic = cleaned_data.get('course_no')

  try:
    course=Course.objects.get(name=name)
  except Course.DoesNotExist:
    course=None

  if course:
    msg = u"Course name: %s has already exist." % name
    self._errors['name'] = self.error_class([msg])
    del cleaned_data['name']
    return cleaned_data
  else:
    return self.cleaned_data

  class Meta:
    model = Course
@login_required
@csrf_protect
@never_cache
@custom_permission_required('records.change_course', 'course')
def edit_course(request,course_id):
  # See if the family exists:
try:
  course = Course.objects.get(id=course_id)
except Course.DoesNotExist:
  course = None

if course:
  if request.method == 'GET':
    form = CourseEditForm(instance=course)
    return render_to_response('records/add.html',
                            {'form': form},
                            context_instance=RequestContext(request)
                            )
  elif request.method == 'POST':
    form = CourseEditForm(request.POST, instance=course)
    if form.is_valid():
      form.save()
      return HttpResponseRedirect('/records/')
    # form is not valid: 
    else:
      error_message = "Please correct all values marked in red."
      return render_to_response('records/edit.html', 
                              {'form': form, 'error_message': error_message},
                              context_instance=RequestContext(request)
                              )      
else:
  error = "Course %s does not exist. Press the 'BACK' button on your browser." % (course)
  return HttpResponseRedirect(reverse('DigitalRecords.views.error', args=(error,)))

谢谢。

我认为您应该在
课程.name
字段上设置
unique=True
,让框架为您处理验证

更新:

由于
unique=True
不是您案例的正确答案,您可以通过以下方式进行检查:

def clean(self):
    """ 
    Override the default clean method to check whether this course has
    been already inputted.
    """    
    cleaned_data = self.cleaned_data
    name = cleaned_data.get('name')

    matching_courses = Course.objects.filter(name=name)
    if self.instance:
        matching_courses = matching_courses.exclude(pk=self.instance.pk)
    if matching_courses.exists():
        msg = u"Course name: %s has already exist." % name
        raise ValidationError(msg)
    else:
        return self.cleaned_data

class Meta:
    model = Course

作为补充说明,我还更改了您的自定义错误处理,以使用更标准的
ValidationError

我相信从结果中排除当前实例id可以解决问题:

from django.db.models import Q
try:
    qs = Course.objects.filter(name=self.cleaned_data.get('name'))
    if self.instance.pk is not None:
        qs = qs.filter(~Q(pk=self.instance.pk))
    course = qs.get()
except Course.DoesNotExist:
    course = None
然而,正如dokkaebi指出的,unique确实是更好的解决方案,因为这种解决方案容易受到种族条件的影响。我不确定您的数据模型是什么样子,但我怀疑

class Meta:
    unique_together = ('department', 'name')

你应该完成你想要的

你的观点是什么?编辑时是否使用
instance
参数用DB对象填充模型表单?我已经添加了视图。谢谢。重点是,如果课程在不同的系下,我允许在数据库中使用相同的课程名称。我想进行检查以避免在同一部门下使用相同的课程名称。如果我想同时检查两个匹配字段的有效性,我需要在其中执行哪些额外操作?
unique\u一起
FTW。永远不要假设你的数据只会被某个特定的网页改变。保护数据完整性的唯一安全方法是尽可能在数据库中强制执行数据完整性。