Значение скрытого поля Django отсутствует в данных POST

Мне нужно отправить данные формы через POST-запрос для сохранения нового экземпляра модели в БД. У меня есть скрытое поле name="owner" в html, которое имеет значение id авторизованного пользователя. Я могу видеть это значение в HTML коде, но не в POST запросе.

Это дает мне Chrome Devtools:

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

И это дает мне отладчик pyCharm:

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

В чем проблема?

У меня есть такой код в 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>

Код формы в 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"),
                }
            ),
        }

Вы можете изменить тип на текст и скрыть его с помощью 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">

Я думаю, что отправленная форма действительно содержит данные owner, но проблема в другом: в вашей owner нет поля AddMarkerForm.

Прежде всего, проверьте, что request.POST содержит "owner": "3" в вашей IDE или терминале, например, просто напечатав его.

Тогда, вероятно, вам придется добавить поле owner к вашему AddMarkerForm. Посмотрите этот другой вопрос на Stackoverflow или эту страницу документации Django, если вам нужна дополнительная помощь.

Вы должны добавить это поле в свою форму для получения его в очищенных данных формы:

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

или если это поле не существует в вашей модели, вы должны определить поле в классе формы:

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

Ваша форма удаляет данные, которые не совпадают с определяемыми полями. Я думаю, что вы можете показать скрытое поле, когда вы печатаете request.POST перед созданием объекта формы.

PS: @Scūriolus опередил меня с ответом

Итак, ни один из ответов выше не сработал для меня. Я решил проблему с помощью следующего кода:

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

А в HTML шаблоне я могу удалить поле:

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

Теперь это работает.

Вернуться на верх