Django form post doesn't contain any values

I have a simple unbound form:

class TeamMemberMapForm(forms.Form):
    remote_id = forms.CharField(widget=forms.HiddenInput())
    project = forms.ModelChoiceField(queryset=Project.objects.none())

Initial values are populated in the get_context_data:

    form.fields['remote_id'].value = remote_id
    form.fields['remote_id'].initial = remote_id
    form.fields['remote_id'].disabled = True
    form.fields['project'].queryset = Project.objects.\
        filter(owned_by_company=self.request.user.owned_by_company, active=True)

On the frontend, I can select the values, by rendering the form like so. This is fine.

{% block form %}
<form method="post">{% csrf_token %}
    <fieldset class="uk-fieldset">
    <!-- {{ form.errors }} -->
    <!-- {{ form.non_field_errors }} -->
    {{ form.as_p }}
    </fieldset>
    <button class="uk-button uk-button-primary" type="submit">
    {% if object %}
    Save {{ object }}
    {% else %}
    Create new entry
    {% endif %}
    </button>
</form>
{% endblock %}

Next, the view. I take the request and populate the form:

    def post(self, request, remote_id, remote_name, *args, **kwargs):
        form = self.form_class(request.POST)

        if form.is_valid():
            # Do whatever

In the end, the form never validates. Inspecting the populated form from the POST shows that the values are never received.

<tr>
    <th><label for="id_remote_id">Remote id:</label></th>
    <td>
      <ul class="errorlist"><li>This field is required.</li></ul>
      <input class="uk-input uk-text " type="text" name="remote_id" required id="id_remote_id">


    </td>
  </tr>

  <tr>
    <th><label for="id_project">Project:</label></th>
    <td>
      <ul class="errorlist"><li>Select a valid choice. That choice is not one of the available choices.</li></ul>
      <select class="uk-select" name="project" required id="id_project">
  <option value="">---------</option>

</select>




    </td>
  </tr>

The post object looks like it contains something for 'project', but not for the remote_id.

<QueryDict: {'csrfmiddlewaretoken': ['zPpsQSHao0BynQWxotu95LiaeF9otrRte3mjYctQuJXgA5ODNi0u8hDDPBfQWaeK'], 'project': ['10']}>

What am I missing?

You can try adding class Meta in your form class:

class TeamMemberMapForm(forms.Form):
    remote_id = forms.CharField(widget=forms.HiddenInput())
    team_member = forms.ModelChoiceField(queryset=TeamMember.objects.none())

    class Meta:
        model = your_model
        fields = ['remote_id','team_member']

And do this function in views.py:

def post(request):
        form = TeamMemberMapForm(request.POST)

        if form.is_valid():
            # Do whatever
        render('url to template', 'form': form)

When you're using a hidden input, you'll need to pass a value to that field. Typically you do this by passing a dictionary to the form;

MyForm(initial={'myfield': "value"})

How you fit this into your view is up to you, but you could do something like;

class MyView(View):


    def get_form(self, form_class=None):
        """Return an instance of the form to be used in this view."""
        if form_class is None:
            form_class = self.get_form_class()
        return form_class(**self.get_form_kwargs())

    def get_form_kwargs(self):
        """Return the keyword arguments for instantiating the form."""
        kwargs = {
            'initial': self.get_initial(),
            'prefix': self.get_prefix(),
        }

        if self.request.method in ('POST', 'PUT'):
            kwargs.update({
                'data': self.request.POST,
                'files': self.request.FILES,
            })
        return kwargs

    def get_context_data(self, **kwargs):
        """Insert the form into the context dict."""
        if 'form' not in kwargs:
            kwargs['form'] = self.get_form()
        return super().get_context_data(**kwargs)

And I made the comment about where to make the query for your form field because by doing it in the field declaration, you're going to be querying the database when your application starts, rather than when you create an instance of the form. This can lead to errors, though I can't recall exactly what error.

Turns out that if you initialise the form with an empty query-set you will no longer be able to adjust it. However, the other way around seems to work.

class TeamMemberMapForm(forms.Form):
    remote_id = forms.CharField(widget=forms.HiddenInput())
    project = forms.ModelChoiceField(queryset=Project.objects.all())

And filter down in the view:

form.fields['project'].queryset = Project.objects.\
    filter(owned_by_company=self.request.user.owned_by_company, active=True)

This seems to reduce the amount of results you get.

Back to Top