【问题标题】:Django form for dynamic hidden input fields用于动态隐藏输入字段的 Django 表单
【发布时间】:2018-01-11 16:59:01
【问题描述】:

我有两个模型,Post 和 Attachment。附件有一个 Post 的外键。

我有一个带有 PostForm 的 PostCreateView。

在撰写文章时,您可以使用 jquery-fileupload (AJAX) 上传图片。如果上传文件,则将以下行附加到<form>

<input type="hidden" name="attachments" value="1" />
<input type="hidden" name="attachments" value="2" />
<input type="hidden" name="attachments" value="3" />

值(1、2和3)是附件模型的PK,以便在我保存帖子时建立帖子和附件之间的关系。

我能够在 PostCreateView 中获得一个列表:

def form_valid(self, form):
    attachments = self.request.POST.getlist('attachments')

但是,我想在 PostForm 中声明表单字段以进行以下验证:

  • PK 必须是整数。
  • 附件的外键在这些 PK 中必须为空。
  • 必须限制 PK 的数量(5 或 10)。

一个帖子可能没有附件,所以附件隐藏输入标签一开始不存在。这就是为什么很难有一个表单域。这些由 AJAX/jQuery 附加。如果很难,我想知道在 CreateView 中应该覆盖哪种方法的最佳实践。

谢谢。

【问题讨论】:

    标签: django forms validation


    【解决方案1】:

    我自己回答。

    1. PostForm 没有 Attachment 的 PK 隐藏字段。

    2. PostAttachmentForm 继承 PostFormclean_attachment() 检查列表项是否都是整数。

      class PostAttachmentForm(PostForm):
          attachments = forms.IntegerField(widget=forms.HiddenInput(), required=False)
      
          def clean_attachments(self):
              data = self.data.getlist('attachments')
      
              if not data and not all(isinstance(item, int) for item in data):
                  raise forms.ValidationError("PK must be integers.")
      
              return data
      
    3. PostCreateView 具有 get_form_class 而不是 form_class 字段。

      def get_form_class(self):
          if self.request.method == 'POST':
              # NOTE: Hidden fields must be validated.
              return PostAttachmentForm
          else:
              # NOTE: Hidden fields are not prepopulated but appended to form by AJAX.
              return PostForm
      
    4. form_valid() 用于 Post 和 Attachment 之间的关系和验证

      def form_valid(self, form):
          response = super().form_valid(form)
      
          # TODO: limit number
      
          # Attachments are not related to any post yet.
          attachments = Attachment.objects.filter(
              pk__in=form.cleaned_data['attachments'],
              post__isnull=True,
          )
          self.object.attachments.set(attachments)
      
          return response
      

    如果您有更好的方法,我将不胜感激。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-18
      • 1970-01-01
      • 2017-06-09
      • 2013-07-23
      • 2014-12-22
      • 2013-02-14
      • 1970-01-01
      • 2012-09-27
      相关资源
      最近更新 更多