Django:ModelMultipleChoiceField 正在将基础模型的 max_length 验证器应用于所选结果的总长度

Django: ModelMultipleChoiceField is applying underlying model's max_length validator to total length of selected results

我正在使用 ModelMultipleChoiceField 允许用户select 删除某些模型对象。当 selected 单个对象时它工作正常,但是当 selected 多个对象时会触发验证错误:“确保此值最多有 50 个字符”。 50 个字符的限制来自基础模型的 max_length 属性。我不确定为什么要进行这种验证,因为我正在 selecting 现有模型对象,更不确定为什么它们要组合我所有 selection 的字符长度而不是验证每个 select离子单独。我还注意到,在总字符长度时,每个对象 selected 大约多了 20 个字符。感谢任何帮助。

这是我的代码:

型号:

class Template(models.Model):
  # Relationships
  user = models.ForeignKey("users.CustomUser", on_delete=models.CASCADE)

  # Fields
  name = models.CharField(max_length=50)
  description = models.TextField(max_length=250)
  docx_file = models.FileField(("DOCX File"), 
    upload_to=user_directory_path, 
    validators=[FileExtensionValidator(allowed_extensions=['docx'])])
  created = models.DateTimeField(auto_now_add=True, editable=False)
  last_updated = models.DateTimeField(auto_now=True, editable=False)

  def __str__(self):
    return self.name

表格:

class TemplateChoiceDelete(forms.ModelForm):
  name = forms.ModelMultipleChoiceField(queryset=Template.objects.all())

  class Meta:
    model = Template
    fields = ['name']

  # Limit results to templates owned by the current user
  def __init__(self, *args, **kwargs):
      user = kwargs.pop('user')
      super(TemplateChoiceDelete, self).__init__(*args, **kwargs)
      self.fields['name'].queryset = Template.objects.filter(user=user)

视图:(忽略过滤器代码,这是与另一个功能相关的正在进行的工作)

def manage_templates(request):
    f = TemplateFilter(request.GET, queryset=Template.objects.filter(user=request.user))
    if request.method == 'GET':
        choice_form = TemplateChoiceDelete(request.GET, user=request.user)
        print(choice_form)
        if choice_form.is_valid():
            choice_form.cleaned_data['name'].delete()
    else:
        form = TemplateChoiceDelete
    return render(request, 'docs/manage_templates.html', {'filter': f, 'choice_form': choice_form})

模板:(再次请忽略与过滤器相关的代码)

{% block content %}
    <p> <b> Search </b> </p>
    <form method="get">
        {{ filter.form.as_p }}
        <input type="submit" value="Search" />
    </form>
    {% for obj in filter.qs %}
        {{ obj.name }} | {{ obj.description }}<br />
    {% endfor %}
    <br>
    <p><b> Delete Templates </b></p>
    <form method="GET">
      {{ choice_form.as_p }}
      <input type="submit" onclick="return confirm('Are you sure? This will delete the selected template(s)')" value="Delete">
    </form>
{% endblock %}

The error

这是不是一个ModelForm,如果你使用ModelForm,它当然会从模型中“继承”某些验证器。这是一个简单的Form,所以:

class TemplateChoiceDelete(<b>forms.Form</b>):
    name = forms.ModelMultipleChoiceField(queryset=Template.objects.all())

    # <i>no</i> Meta

    # Limit results to templates owned by the current user
    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        super().__init__(*args, **kwargs)
        self.fields['name'].queryset = Template.objects.filter(user=user)

ModelForm 是针对特定模型定制的 Form 以创建或更新模型 实例 ,而不是编辑具有“有事可做”与那个模型。


Note: Section 9 of the HTTP protocol specifies that requests like GET and HEAD should not have side-effets, so you should not change entities with such requests. Normally POST, PUT, PATCH, and DELETE requests are used for this. In that case you make a small <form> that will trigger a POST request, or you use some AJAX calls.