Formularios Django
Los formularios HTML son la forma clásica de interactividad en los sitios web. Este capítulo presentará cómo usar Django para procesar los datos de formularios enviados por los usuarios.
Solicitud HTTP
El protocolo HTTP funciona de manera "solicitud-respuesta". Cuando el cliente envía una solicitud, puede adjuntar datos a la misma. El servidor, al analizar la solicitud, puede obtener los datos enviados por el cliente y proporcionar servicios específicos según la URL.
Método GET
En el proyecto anterior, creamos un archivo search.py para recibir las solicitudes del usuario:
/HelloWorld/HelloWorld/search.py Código del archivo:
Agrega el formulario search_form.html en el directorio de plantillas templates:
/HelloWorld/templates/search_form.html Código del archivo:
Modifica las reglas de urls.py de la siguiente manera:
/HelloWorld/HelloWorld/urls.py Código del archivo:
Dirección de accesohttp://127.0.0.1:8000/search-form/Y al buscar, el resultado es el siguiente:

Método POST
Arriba usamos el método GET, donde la visualización de la vista y el procesamiento de la solicitud se manejan en dos funciones separadas.
El método POST se usa más comúnmente al enviar datos. A continuación usaremos este método, y con una URL y una función de procesamiento, mostraremos la vista y procesaremos la solicitud al mismo tiempo.
Creamos post.html en templates:
/HelloWorld/templates/post.html Código del archivo:
Al final de la plantilla, agregamos una marca rlt para reservar un lugar para el resultado del procesamiento del formulario.
Después del formulario, también hay una{% csrf_token %}etiqueta. El nombre completo de csrf es Cross Site Request Forgery. Esta es una funcionalidad que Django proporciona para evitar solicitudes de envío disfrazadas. Los formularios enviados con el método POST deben tener esta etiqueta.
En el directorio HelloWorld, crea un nuevo archivo search2.py y usa la función search_post para procesar las solicitudes POST:
/HelloWorld/HelloWorld/search2.py Código del archivo:
Modifica las reglas de urls.py de la siguiente manera:
/HelloWorld/HelloWorld/urls.py Código del archivo:
Visitahttp://127.0.0.1:8000/search-post/El resultado se muestra a continuación:
Después de completar el ejemplo anterior, nuestra estructura de directorios es la siguiente:
HelloWorld
|-- HelloWorld
| |-- __init__.py
| |-- __init__.pyc
| |-- search.py
| |-- search.pyc
| |-- search2.py
| |-- search2.pyc
| |-- settings.py
| |-- settings.pyc
| |-- testdb.py
| |-- testdb.pyc
| |-- urls.py
| |-- urls.pyc
| |-- views.py
| |-- views.pyc
| |-- wsgi.py
| `-- wsgi.pyc
|-- TestModel
| |-- __init__.py
| |-- __init__.pyc
| |-- admin.py
| |-- admin.pyc
| |-- apps.py
| |-- migrations
| | |-- 0001_initial.py
| | |-- 0001_initial.pyc
| | |-- __init__.py
| | `-- __init__.pyc
| |-- models.py
| |-- models.pyc
| |-- tests.py
| `-- views.py
|-- db.sqlite3
|-- manage.py
`-- templates
|-- base.html
|-- hello.html
|-- post.html
`-- search_form.html
Objeto Request
El primer parámetro de cada función de vista es un objeto HttpRequest, como en la siguiente función ejemplo():
from django.http import HttpResponse
def ejemplo(request):
return HttpResponse("Hello world")
El objeto HttpRequest contiene información sobre la URL de la solicitud actual:
|
Atributo |
Descripción |
|
path |
La ruta completa de la página solicitada, sin incluir el dominio—por ejemplo, "/hello/". |
|
method |
Representación de cadena del método HTTP utilizado en la solicitud. En mayúsculas. Por ejemplo: if request.method == 'GET': |
|
GET |
Objeto similar a diccionario que contiene todos los parámetros HTTP GET. Consulta la documentación de QueryDict. |
|
POST |
Objeto similar a diccionario que contiene todos los parámetros HTTP POST. Consulta la documentación de QueryDict. Es posible que el servidor reciba una solicitud POST vacía. Es decir, el formulario envía la solicitud mediante el método HTTP POST, pero el formulario puede no contener datos. Por lo tanto, no se puede usar la sentencia if request.POST para determinar si se utiliza el método HTTP POST; se debe usar if request.method == "POST" (consulta el atributo method de esta tabla). Nota: POST no incluye información de carga de archivos. Consulta el atributo FILES. |
|
REQUEST |
Por conveniencia, este atributo es una combinación de los atributos POST y GET, pero tiene una particularidad: busca primero en el atributo POST y luego en el atributo GET. Se basa en el $_REQUEST de PHP. Por ejemplo, si GET = {"name": "john"} y POST = {"age": '34'}, entonces el valor de REQUEST["name"] es "john" y el valor de REQUEST["age"] es "34". Se recomienda encarecidamente usar GET y POST, porque estos dos atributos son más explícitos y el código escrito es más fácil de entender. |
|
COOKIES |
Objeto de diccionario estándar de Python que contiene todas las cookies. Las claves y los valores son cadenas. |
|
FILES |
Objeto similar a diccionario que contiene todos los archivos subidos. Cada clave en FILES es el valor del atributo name en la etiqueta <input type="file" name="" />. Cada valor en FILES también es un objeto de diccionario estándar de Python que contiene las siguientes tres claves:
Nota: FILES solo tiene datos si el método de solicitud es POST y la página de solicitud tiene el atributo enctype="multipart/form-data" en el <form>. De lo contrario, FILES es un diccionario vacío. |
|
META |
Diccionario que contiene toda la información disponible de los encabezados HTTP. Por ejemplo:
En META, estos encabezados con el prefijoHTTP_como clave, y lo que sigue a los dos puntos (:) es el valor. Por ejemplo:
|
|
user |
Es un objeto django.contrib.auth.models.User que representa al usuario actualmente conectado. Si el usuario visitante no ha iniciado sesión, user se inicializará como una instancia de django.contrib.auth.models.AnonymousUser. Puedes determinar si el usuario ha iniciado sesión mediante el método is_authenticated() de user:
if request.user.is_authenticated():
# Do something for logged-in users.
else:
# Do something for anonymous users.
Este atributo solo está disponible cuando AuthenticationMiddleware de Django está activado. |
|
session |
El único atributo de lectura y escritura, representa el objeto de diccionario de la sesión actual. Este atributo solo está disponible cuando el soporte de sesiones de Django está activado. |
|
raw_post_data |
Datos HTTP POST originales, sin analizar. Son útiles para el procesamiento avanzado. |
El objeto Request también tiene algunos métodos útiles:
| Método | Descripción |
|---|---|
| __getitem__(key) | Devuelve el valor de la clave GET/POST, primero toma POST y luego GET. Si la clave no existe, lanza KeyError. Esto nos permite acceder al objeto HttpRequest con la sintaxis de diccionario. Por ejemplo, request["foo"] equivale a intentar primero request.POST["foo"] y luego request.GET["foo"]. |
| has_key() | Verificar si request.GET o request.POST contiene la clave especificada por el parámetro. |
| get_full_path() | Devuelve la ruta de la solicitud que contiene la cadena de consulta. Por ejemplo, "/music/bands/the_beatles/?print=true" |
| is_secure() | Devuelve True si la solicitud es segura, es decir, si se realizó mediante una solicitud HTTPS. |
Objeto QueryDict
En el objeto HttpRequest, los atributos GET y POST son instancias de la clase django.http.QueryDict.
QueryDict es una clase personalizada similar a un diccionario, que se utiliza para manejar el caso de que una sola clave corresponda a múltiples valores.
QueryDict implementa todos los métodos estándar de diccionario. También incluye algunos métodos específicos:
| Método | Descripción |
|---|---|
|
__getitem__ |
Hay una pequeña diferencia con el manejo del diccionario estándar: si la clave corresponde a múltiples valores, __getitem__() devuelve el último valor. |
|
__setitem__ |
Establece la lista de valores (una lista de Python) para la clave especificada por el parámetro. Nota: solo se puede llamar en un objeto QueryDict mutable (es decir, una copia de un objeto QueryDict creada mediante copy()). |
|
get() |
Si la clave corresponde a múltiples valores, get() devuelve el último valor. |
|
update() |
El parámetro puede ser un QueryDict o un diccionario estándar. A diferencia del método update del diccionario estándar, este método agrega los items del diccionario, en lugar de reemplazarlos:
>>> q = QueryDict('a=1')
>>> q = q.copy() # to make it mutable
>>> q.update({'a': '2'})
>>> q.getlist('a')
['1', '2']
>>> q['a'] # returns the last
['2']
|
|
items() |
Hay una pequeña diferencia con el método items() del diccionario estándar: este método utiliza __getitem__() con lógica de valor único:
>>> q = QueryDict('a=1&a=2&a=3')
>>> q.items()
[('a', '3')]
|
|
values() |
Hay una pequeña diferencia con el método values() del diccionario estándar: este método utiliza __getitem__() con lógica de valor único: |
Además, QueryDict también tiene algunos métodos, como se muestra en la siguiente tabla:
| Método | Descripción |
|---|---|
|
copy() |
Devuelve una copia del objeto, implementada internamente con copy.deepcopy() de la biblioteca estándar de Python. Esta copia es mutable (modificable), es decir, se pueden cambiar los valores de la copia. |
|
getlist(key) |
Devuelve todos los valores correspondientes a la clave del parámetro, como una lista de Python. Si la clave no existe, devuelve una lista vacía. Se garantiza que devuelve una lista de algún tipo. |
|
setlist(key,list_) |
Establece el valor de la clave como list_ (a diferencia de __setitem__()). |
|
appendlist(key,item) |
Agrega un item a la lista interna asociada con la clave. |
|
setlistdefault(key,list) |
Hay una pequeña diferencia con setdefault: acepta una lista en lugar de un solo valor como parámetro. |
|
lists() |
Hay una pequeña diferencia con items(): devuelve todos los valores de la clave, como una lista, por ejemplo:
>>> q = QueryDict('a=1&a=2&a=3')
>>> q.lists()
[('a', ['1', '2', '3'])]
|
|
urlencode() |
Devuelve una cadena formateada como cadena de consulta (por ejemplo: "a=2&b=3&b=5"). |