Значение скрытого поля 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 %}">
Теперь это работает.