Одной из форм отправки данных на сервер представляет отправка с помощью форм 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>