Django hidden field value is not in POST data

Viewed 39

I need to send form data via POST request to save a new model instance to DB. I have a hidden field name="owner" in html which has a value of authorized user id. I can see this value in HTML code, but not in POST request.

This gives me Chrome Devtools:

<input type="hidden" id="owner" name="owner" value="3">

And this gives me a pyCharm's debugger:

cleaned_data = {'latitude': 55.2288, 'longitude': 24.3686, 'comment': '', 'category': <Category: Host>}

What is the problem?

I have this code in Django views.py:

if request.method == "POST":
    form = AddMarkerForm(request.POST)
    if form.is_valid():
        form.save()
        messages.success(
            request, _("Marker added successfully!"), extra_tags="success"
        )
        return redirect(to="home")
    else:
        messages.error(request, _("Error. Check coordinates."), extra_tags="danger")
else:
    form = AddMarkerForm()

And html:

                <form class="row g-3" method="post" enctype="multipart/form-data"
                      id="addMarkerForm" name="addMarkerForm">
                    {% csrf_token %}
                    {% for field in form.visible_fields|slice:":2" %}
                        <div class="col-md-6">
                            {{ field }}
                        </div>
                    {% endfor %}
                    {% for field in form.visible_fields|slice:"2:" %}
                        <div class="col-12">
                            {{ field }}
                        </div>
                    {% endfor %}
                    <input type="hidden" id="owner" name="owner"
                           value="{% if request.user %}{{ request.user.id }}{% endif %}">
                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary"
                                data-bs-dismiss="modal">{% translate "Close" %}</button>
                        <button type="submit" name="submit" class="btn btn-primary">{% translate "Add" %}</button>
                    </div>
                </form>

A form code in forms.py:

class AddMarkerForm(forms.ModelForm):
    """Form for adding a new marker on a frontend."""

    latitude = forms.FloatField(
        widget=forms.TextInput(
            attrs={
                "class": "form-control",
                "id": "latitude",
                "placeholder": _("Latitude"),
            }
        ),
    )
    longitude = forms.FloatField(
        widget=forms.TextInput(
            attrs={
                "class": "form-control",
                "id": "longitude",
                "placeholder": _("Longitude"),
            }
        )
    )
    category = forms.ModelChoiceField(
        queryset=Category.objects.all(),
        empty_label=_("Choose category"),
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    class Meta:
        model = Marker
        fields = ["latitude", "longitude", "comment", "category"]
        widgets = {
            "comment": forms.Textarea(
                attrs={
                    "class": "form-control",
                    "rows": 3,
                    "max-length": 200,
                    "placeholder": _("Comment, not required"),
                }
            ),
        }
4 Answers

I think that the submitted form does contain the owner data, but that the problem is elsewhere: there isn't any field owner in your AddMarkerForm.

First of all, check that request.POST does contain "owner": "3" in your IDE or terminal by simply printing it for instance.

Then, you'll probably have to add a field owner to your AddMarkerForm. See this other Stackoverflow question or this page of the Django documentation if you need more help.

You have to add this field in your form for retrieve it in the cleaned_data of the form:

fields = ["latitude", "longitude", "comment", "category", "owner"]

or if this field does not exist in your model, you have to define a field in form class:

owner = forms.ModelChoiceField(queryset=get_user_model().objects.all())

Your form remove data which not match with defines fields. I think you can show your hidden field when you print request.POST before create your form object.

PS: @Scūriolus got ahead of me for the answer

So, none of the answers above worked for me. I've handled the issue with this code:

if request.method == "POST":
    form = AddMarkerForm(request.POST)
    if form.is_valid():
        form = form.save(commit=False)
        form.owner = request.user
        form.save()

And in HTML template I might to delete field:

<input type="hidden" id="owner" name="owner" value="{% if request.user %}{{ request.user.id }}{% endif %}">

Now it works.

You can change the type to text and hide it with CSS:

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
}

<input type="text" id="owner" class="sr-only" name="owner" value="3">
Related