1

我正在使用 ModelMultipleChoiceField 来允许用户选择要删除的某些模型对象。It works fine when a single object is selected, but when multiple objects are selected then a validation error is triggered: "Ensure this value has at most 50 characters". 50 个字符的限制来自基础模型的 max_length 属性。我不确定为什么会发生这种验证,因为我正在选择现有的模型对象,更不确定为什么它们会组合我所有选择的字符长度而不是单独验证每个选择。我还注意到,在总计字符长度时,为每个选定的对象计算大约 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 %}

错误

4

1 回答 1

1

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

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

    # no 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)

AModelFormForm针对特定模型量身定制的,以创建或更新模型实例,而不是编辑与该模型“有关系”的项目。


注意HTTP 协议第 9 节 规定,像 GET 和 HEAD 这样的请求不应副作用,因此您不应使用此类请求更改实体。通常 POST、PUT、PATCH 和 DELETE 请求用于此目的。在这种情况下,您制作一个<form>会触发 POST 请求的小程序,或者您使用一些 AJAX 调用。

于 2020-12-02T18:36:29.757 回答