Одной из форм отправки данных на сервер представляет отправка с помощью форм html, обычно в запросе типа POST. В Django в целом можно использовать два подхода для работы с формами. Во-первых, можно работать со стандартными формами html. Во-вторых, Django также предоставляет специальный функционал для работы с формами, который, возможно, в каких-то моментах упрощает работу с данными. В даннной главе рассмотрим оба подхода. А в данной статье посмотрим, как получать данные обычных форм html.
Обычно данные форм передаются на сервер в запросе типа POST. Для получения подобных данных в классе HttpRequest определено свойство POST. Например, пусть у нас есть следующий шаблон index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>METANIT.COM</title>
</head>
<body>
<h2>User form</h2>
<form method="post" action="postuser/">
{% csrf_token %}
<p>Name:<br> <input name="name" /></p>
<p>Age:<br> <input name="age" type="number" /></p>
<input type="submit" value="Send" />
</form>
</body>
</html>
Здесь определена форма условно для ввода данных пользователя, которая в запросе типа POST (атрибут method="post") отправляет данные по адресу "postuser/"
(атрибут action="postuser/").
На форме определены два поля ввода. Первое поле предназначено для ввода имени пользователя. Второе поле - для ввода возроста пользователя.
Также внутри формы используется тег {% csrf_token %}. Он позволяет защитить приложение от CSRF-атак, добавляя в форму в виде скрытого поля csrf-токен.
Кроме того, Django по умолчанию требует наличия данного токена в получаемых данных в запросе POST.
Для отправки формы и получения ее данных определим в файле views.py следующие функции:
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return render(request, "index.html")
def postuser(request):
# получаем из данных запроса POST отправленные через форму данные
name = request.POST.get("name", "Undefined")
age = request.POST.get("age", 1)
return HttpResponse(f"<h2>Name: {name} Age: {age}</h2>")
В представлении index возвращается шаблон, который содержит форму ввода.
В представлении postuser получаем через словарь request.POST отправленные из формы данные. В этом словаре по ключу можно получить
значение элемента. При этом в качестве ключей выступает названия полей форм (значения атрибутов name элементов формы):
<input name="age" type="number" />
Так, в данном случае название поля (значение атрибута name) равно "age". Соответственно в request.POST по этому имени мы можем получить его значение:
age = request.POST.get("age", 1)
Если по каким-то причинам данные с ключом "age" в запросе отсутствуют, то возвращается значени по умолчанию - 1.
Далее в файле urls.py свяжем эти функции с маршрутами:
from django.urls import path
from hello import views
urlpatterns = [
path("", views.index),
path("postuser/", views.postuser),
]
И после получения данных формы они отправляются обратно клиенту:
Усложним задачу и добавим в форму на странице index.html несколько полей, которые будут представлять массив:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>METANIT.COM</title>
</head>
<body>
<h2>User form</h2>
<form method="post" action="postuser/">
{% csrf_token %}
<p>Name:<br /> <input name="name" /></p>
<p>Age:<br /> <input name="age" type="number" /></p>
<p>
Languages:<br />
<input name="languages" /><br />
<input name="languages" /><br />
<input name="languages" /><br />
</p>
<input type="submit" value="Send" />
</form>
</body>
</html>
Здесь практически та же форма, только добавлено три поля для ввода языка программирования. Причем каждое из этих полей имеет одно и то же имя - "languages". Благодаря этому при отправке формы в данных запроса будет сформирован список languages из данных, введенных в эти поля.
В файле views.py изменим функцию postuser для получения массива languages:
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return render(request, "index.html")
def postuser(request):
# получаем из строки запроса имя пользователя
name = request.POST.get("name", "Undefined")
age = request.POST.get("age", 1)
langs = request.POST.getlist("languages", ["python"])
return HttpResponse(f"""
<div>Name: {name} Age: {age}<div>
<div>Languages: {langs}</div>
""")
Ключевой компонент при получении списка данных из запроса представляет метод getlist(), который работает так же, как и get(),
только возвращает список. Если в запросе не окажется данных с ключом languages, то возвращаем список ["python"]
Получив список, мы можем что-то сделать с его элементами, перебрать, обратиться к элементам по индексу и т.д. Но в данном случае просто передаем весь список в формируемый ответ.
Подобным образом можно передавать значения массива полей других типов, либо полей, которые представляют набор элементов, например, элемента select, который поддерживает множественный выбор:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>METANIT.COM</title>
</head>
<body>
<h2>User form</h2>
<form method="post" action="postuser/">
{% csrf_token %}
<p>Name: <br />
<input name="name" />
</p>
<p>Age: <br />
<input name="age" type="number" />
</p>
<p>
Languages:<br />
<select multiple name="languages">
<option>Python</option>
<option>JavaScript</option>
<option>C++</option>
<option>Java</option>
</select>
</p>
<input type="submit" value="Send" />
</form>
</body>
</html>