简体   繁体   中英

How to put a value from request.GET as a hidden input in django-crispy-forms

As an example, let's take a look at the 'next' parameter in django.contrib.auth

If the client is trying to access some resources which is only available for authenticated users, the login url will be modified and attached with extra parameter as ?next=the_next_url . Then, the LoginForm could set this parameter into context_data and generate a form with a hidden input which contains its value like

{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}

However, how can I do this if I generate the form completely with django-crispy-form? In this case, the template file contains nothing but

{% crispy_tag form %}

form will be set as context data, which means I have to push the parameter from request.GET in the form as a hidden input widget.

How could I do this?

Finally, I figured it out by myself.

To solve this problem, the context_data in the original template based solution should be passed as initial into the constructor of forms.Form .

For example, with django CVB, get_initial is the right point to pass initial data to forms

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

Then, it is possible to add a field dynamically in the instance of 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
    )
  )

You can ask Django Crispy Form to not render the <form> tag, and only generate the <input> tags, which will let you then add your own extra <input> .

You do this by setting the form helper's form_tag property to False .

This is all documented in detail here . Note that unlike the example, you won't need {% crispy second_form %} , you'll only need to add your own if block there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM