如何将 request.GET 中的值作为 django-crispy-forms 中的隐藏输入

jca*_*dam 3 python forms django

举个例子,让我们看看 django.contrib.auth 中的“next”参数

如果客户端尝试访问某些仅对经过身份验证的用户可用的资源,则登录 url 将被修改并附加额外的参数 as ?next=the_next_url。然后,LoginForm可以将此参数设置为context_data并生成一个带有隐藏输入的表单,其中包含其值,如

{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
Run Code Online (Sandbox Code Playgroud)

但是,如果我完全使用 django-crispy-form 生成表单,我该怎么做?在这种情况下,模板文件只包含

{% crispy_tag form %}
Run Code Online (Sandbox Code Playgroud)

form 将被设置为上下文数据,这意味着我必须将 request.GET 表单中的参数作为隐藏的输入小部件推送。

我怎么能这样做?

jca*_*dam 5

最后,我自己想通了。

为了解决这个问题,原始基于模板的解决方案中的 context_data 应该被传递initial到 的构造函数中forms.Form

例如,使用 django CVB,get_initial是将初始数据传递给表单的正确点

def get_initial(self):
  initial = Super(ThisCBV, self).get_initial()
  redirect_field_name = self.get_redirect_field_name()
  if (redirect_field_name in self.request.GET and 
      redirect_field_value in self.request.GET):
      initial.update({
           "redirect_field_name": redirect_field_name,
           "redirect_field_value": self.request.REQUEST.get(
               redirect_field_name),
      })
  return initial
Run Code Online (Sandbox Code Playgroud)

那么,就可以在forms.Form的实例中动态添加一个字段

def __init__(self, *args, **kwargs):
  super(ThisForm, self).__init__(*args, **kwargs)
  if ('redirect_field_name' in kwargs['initial'] and
      'redirect_field_value' in kwargs['initial']):

      self.has_redirection = True
      self.redirect_field_name = kwargs['initial'].get('redirect_field_name')
      self.redirect_field_value = kwargs['initial'].get('redirect_field_value')

      ## dynamically add a field into form
      hidden_field = forms.CharField(widget=forms.HiddenInput())
      self.fields.update({
        self.redirect_field_name: hidden_field
      })

  ## show this field in layout
  self.helper = FormHelper()
  self.helper.layout = Layout(
    Field(
      self.redirect_field_name,
      type='hidden',
      value=self.redirect_field_value
    )
  )
Run Code Online (Sandbox Code Playgroud)