2020 Documentación - Django 3.1
2020 Documentación - Django 3.1
Documentation
Django de un vistazo
Diseñe su modelo
Instálelo
Instale Python
Instale Django
Comprobando
¡Eso es todo!
Creando un proyecto
El servidor de desarrollo
Creando modelos
Información general
Pruebas adicionales
¿Qué sigue?
¿Qué sigue?
La reusabilidad importa
Empaquetando su aplicación
Publicando su aplicación
Buscando documentación
Dónde conseguirla
Introducción
Código de Conducta
Instalando Git
Escribiendo la documentación
Próximos pasos
Using Django
Install Python
Models
Making queries
Aggregation
Search
Managers
Database transactions
Multiple databases
Tablespaces
Database instrumentation
URL dispatcher
Writing views
View decorators
File Uploads
Generic views
Middleware
HTML forms
Forms in Django
Building a form
Further topics
Templates
Class-based views
Basic examples
Migrations
The Commands
Backend Support
Work ow
Dependencies
Migration les
Adding migrations to apps
Reversing migrations
Historical models
Data Migrations
Squashing migrations
Serializing values
Managing les
File storage
Testing in Django
Testing tools
Overview
Installation
Usage
Downstream caches
Order of MIDDLEWARE
Cryptographic signing
Sending email
Quick example
send_mail()
send_mass_mail()
mail_admins()
mail_managers()
Examples
Overview
De nitions
Logging
Using logging
Pagination
Example
Paginating a ListView
Security in Django
Clickjacking protection
SSL/HTTPS
Referrer policy
Session security
User-uploaded content
Introduction
General approaches
Caching
Understanding laziness
Databases
HTTP performance
Template performance
Serializing data
Deserializing data
Serialization formats
Natural keys
Django settings
The basics
Default settings
Available settings
Signals
Listening to signals
Disconnecting signals
External packages
Local avor
Comments
Formtools
Asynchronous support
Async views
Async safety
«How-to» guides
Con guración
Testing
Overriding commands
Objetos de Comando
Introducción
Fundamentos teóricos
Búsquedas personalizadas
A lookup example
A transformer example
How Django determines the lookups and transforms which are used
Custom backends
Code layout
Deploying Django
Deployment checklist
Required Reading
Dependencies
Installation
Testing
Deployment
Error reporting
Install ReportLab
Other formats
Overriding templates
Testing
Deployment
Learn more
Learn more
Instale Python
About pip
Instale Django
Common pitfalls
FAQ de Django
FAQ: General
Django parece ser un framework MVC, pero ustedes llaman al Controlador «vista», y a la Vista «plantilla». ¿Cómo es que no usan los nombres estándares?
¿Por qué escribieron todo Django desde cero en vez de usar otras librerías de Python?
FAQ: Instalación
¿Cómo comienzo?
¿Cómo hago que una variable esté disponible para todas mis plantillas?
¿Cómo puedo ver las consultas SQL plano que Django está ejecutando?
¿Puedo usar Django con una base de datos ya existente?
¿Cómo añado opciones especí cas de la base de datos a mis sentencias CREATE TABLE, tales como establecer MyISAM como el tipo de tabla?
No puedo ingresar. Cuando ingreso un usuario y contraseña válidos, me muestra de nuevo la página de inicio de sesión sin ningún mensaje de error.
No puedo ingresar. Cuando uso un usuario y contraseña válidos, me muestra la página de inicio de sesión de nuevo con un mensaje de error de «Por favor introduzca el
usuario y contraseña correctos».
¿Cómo jo automáticamente el valor de un campo al último usuario que editó el objeto en el sitio administrativo?
¿Cómo limito el acceso en el sitio administrativo de manera que los objetos solo puedan ser modi cados por los usuarios que los crearon?
Las CSS e imágenes de mi sitio administrativo se muestran bien mientras uso el servidor de desarrollo, pero no se muestran cuando uso mod_wsgi.
¡El sitio administrativo generado de forma dinámica se ve feo! ¿Cómo puedo modi carlo?
Presenté un parche en el sistema de tickets hace varias semanas. ¿Por qué lo ignoran?
Miscelánea
API Reference
Applications
Application registry
Initialization process
API reference
Builtin tags
Base views
Speci cation
Clickjacking Protection
An example of clickjacking
Preventing clickjacking
How to use it
Limitations
contrib packages
django.contrib.auth
GeoDjango
django.contrib.humanize
django.contrib.postgres
admin
auth
contenttypes
flatpages
gis
humanize
messages
postgres
redirects
sessions
sites
sitemaps
syndication
Other add-ons
How to use it
Rejected requests
How it works
Caching
Testing
Limitations
Edge cases
Settings
Databases
General notes
PostgreSQL notes
MariaDB notes
MySQL notes
SQLite notes
Oracle notes
Usage
Available commands
Default options
Extra niceties
Output redirection
Django Exceptions
Database Exceptions
Http Exceptions
Transaction Exceptions
Python Exceptions
File handling
Forms
Form elds
Formset Functions
Widgets
Middleware
Available middleware
Middleware ordering
Migration Operations
Schema Operations
Special Operations
Models
Constraints reference
Query Expressions
Conditional Expressions
Database Functions
Paginator
Paginator class
Page class
Exceptions
Quick overview
HttpRequest objects
QueryDict objects
HttpResponse objects
JsonResponse objects
StreamingHttpResponse objects
FileResponse objects
SchemaEditor
Methods
Attributes
Settings
Core Settings
Auth
Messages
Sessions
Sites
Static Files
Signals
Model signals
Management signals
Request/response signals
Test signals
Database Wrappers
Templates
SimpleTemplateResponse objects
TemplateResponse objects
Unicode data
Creating the database
Models
Templates
Files
Form submission
reverse()
reverse_lazy()
resolve()
get_script_prefix()
path()
re_path()
include()
register_converter()
static()
url()
handler400
handler403
handler404
handler500
Django Utils
django.utils.cache
django.utils.dateparse
django.utils.decorators
django.utils.encoding
django.utils.feedgenerator
django.utils.functional
django.utils.html
django.utils.http
django.utils.module_loading
django.utils.safestring
django.utils.text
django.utils.timezone
django.utils.translation
Validators
Writing validators
Built-in validators
Built-in Views
Error views
Estabilidad de la API
Qué signi ca «estable»
APIs estables
Excepciones
Filosofía de diseño
En general
Modelos
Diseño de URLs
Sistema de plantillas
Vistas
Framework caché
Glosario de términos
Release notes
Final releases
3.1 release
3.0 release
2.2 release
2.1 release
2.0 release
1.11 release
1.10 release
1.9 release
1.8 release
1.7 release
1.6 release
1.5 release
1.4 release
1.3 release
1.2 release
1.1 release
1.0 release
Pre-1.0 releases
Security releases
Django internals
Writing code
Writing documentation
Localizando Django
Mailing lists
django-users
django-core-mentorship
django-developers
django-i18n
django-announce
django-updates
Principles
Core team
Technical board
Supported versions
O cial releases
Release cadence
Deprecation policy
Supported versions
Release process
4.0
3.1
3.0
2.1
2.0
1.10
1.9
1.8
1.7
1.6
1.5
1.4
1.3
High-level overview
Stable branches
Etiquetas
Información general
Prerequisites
Pre-release tasks
Índice de Módulos
Glosario de términos
Documentación de Django
Todo lo que necesita saber sobre Django.
Tutorial: Parte 1: Peticiones y respuestas | Parte 2: Modelos y el sitio administrativo | Parte 3: Vistas y plantillas | Parte 5: Pruebas | Parte 6: Archivos estáticos | Parte 7:
Personalizando el sitio administrativo
Tutoriales avanzados: Cómo escribir aplicaciones reutilizables | Creando tu primer parche para Django
Obtener ayuda
¿Tiene algún problema? ¡Nos gustaría ayudar!
Prueba con las Preguntas Frecuentes – contienen las respuestas a muchas preguntas comunes.
¿Buscando información especí ca? Intente con Índice, Índice de Módulos o la tabla de contenidos detallada.
Not found anything? See FAQ: Obteniendo ayuda for information on getting support and asking questions to the community.
Tutorials take you by the hand through a series of steps to create a Web application. Start here if you’re new to Django or Web application development. Also look at the «Los
primeros pasos».
Guías temáticas discuten los temas y conceptos fundamentales en un nivel bastante alto y proporcionan información y explicación de antecedentes valiosa.
Guías de referencia contienen la referencia técnica para las APIs y otros aspectos del sistema de Django. Ellas describen cómo funciona y cómo utilizarla, pero da por sentado que
usted tiene un conocimiento básico de los conceptos claves.
Las guías de uso son fórmulas. Lo guian a través de los pasos involucrados en abordar los problemas principales y los casos de uso. Son más avanzadas que los tutoriales y dan
por sentado el tener algo de conocimiento sobre cómo funciona Django.
Modelos: Introducción a los modelos | Tipos de campos | Índices | Opciones Meta | Clase Model
Advanced: Managers | Raw SQL | Transactions | Aggregation | Search | Custom elds | Multiple databases | Custom lookups | Query Expressions | Conditional Expressions |
Database Functions
Otros: Bases de datos soportadas | Bases de datos heredadas | Proporcionando los datos iniciales | Optimizar el acceso a la base de datos | Características especí cas de
PostgreSQL
La capa de vista
Django tiene el concepto de «vistas» para encapsular la lógica responsable de procesar una petición del usuario y devolver la respuesta. Encuentre todo lo que necesita saber sobre las
vistas a través de los enlaces que siguen:
Carga de archivos: Visión general | Objetos de archivo | API de almacenamiento | Gestión de archivos | Almacenamiento personalizado
Vistas basadas en clases: Visión general | Vistas incorporadas para visualización | Vistas incorpordas para edición | Usando Mixins | Referencia de la API | Índice estático
Avanzado: Generación de archivos CSV | Generación de archivos PDF
La capa de plantillas
La capa de plantillas provee una sintaxis amigable para los diseñadores que permite mostrar la información que se presentará al usuario. Aprenda cómo esta sintaxis puede ser usada
por los diseñadores y extendida por los programadores:
Para los diseñadores: Información general del lenguaje | Etiquetas y ltros incorporados | Humanización
For programmers: Template API | Custom tags and lters | Custom template backend
Formularios
Django provee un poderoso framework para facilitar la creación de formularios y la manipulación de sus datos.
Avanzado: Formularios para modelos | Integración de medios | Juegos de formularios | Personalización de la validación
El proceso de desarrollo
Aprenda sobre los diversos componentes y herramientas para ayudarse en el desarrollo y pruebas de aplicaciones Django:
Pruebas: Introducción | Confección y ejecución de pruebas | Herramientas de pruebas incluidas | Temas avanzados
Deployment: Overview | WSGI servers | ASGI servers | Deploying static les | Tracking code errors by email | Deployment checklist
El sitio administrativo
Encuentre todo lo que necesita saber acerca de la interfaz administrativa automatizada, una de las funcionalidades más populares de Django:
Sitio administrativo
Seguridad
La seguridad es un tema de suma importancia en el desarrollo de aplicaciones Web y Django provee múltiples herramientas y mecanismos de protección:
Firma criptográ ca
Middleware de seguridad
Internacionalización y localización
Django ofrece un robusto framework de internacionalización y localización para ayudarle en el desarrollo de aplicaciones para múltiples idiomas y regiones del mundo:
Información general | Internacionalización | Localización | formato localizado de la interfaz Web y entrada de formulario
Husos horarios
Rendimiento y optimización
Existe una variedad de técnicas y herramientas que lo pueden ayudar a ejecutar el código de forma más e ciente y rápida y con menos uso de recursos del sistema.
Framework geográ co
GeoDjango tiene como propósito ser un framework para el desarrollo geográ co de clase mundial. Su meta es hacer lo más fácil posible construir aplicaciones GIS Web y aprovechar el
poder de los datos habilitados de forma espacial.
Autenticación: Información general | Usando el sistema de autenticación | Gestión de contraseñas | Personalizando la autenticación | Referencia de la API
Almacenamiento en caché
Registro
Enviando correos
Paginado
Framework de mensajes
Serialización
Sesiones
Mapas de sitio
Validación de datos
Páginas estáticas
Redirecciones
Señales
El framework de sitios
Unicode en Django
Comunidad: Cómo involucrarse | El proceso de liberación | Organización del equipo | El repositorio de código fuente de Django | Políticas de seguridad | Listas de correo
Django en el tiempo: Estabilidad de la API | Notas de versión e instrucciones de actualización | Linea de tiempo de funcionalidades en desuso
Empezando
¿Es nuevo en Django o en el desarrollo Web en general? Bueno, ha venido al lugar indicado: lea este material para que se ponga en marcha rápidamente.
Django de un vistazo
Ver también
Si es nuevo en Python, es posible que desee empezar por familiarizarse con el lenguaje. Django es 100% Python, así que si tiene un conocimiento mínimo de
Python probablemente obtendrá mucho más de Django.
Si eres totalmente nuevo en la programación, es posible que desee comenzar con esta lista de recursos de Python para los que no son programadores
Si ya conoce otros lenguajes y quiere ponerse al día con Python rápidamente, recomendamos Inmersión en Python. Si ese no es del todo su estilo, hay muchos
otros libros sobre Python.
Django de un vistazo
Debido a que Django fue desarrollado en un ambiente de sala de redacción de ritmo rápido, fue diseñado para hacer tareas comunes de desarrollo web de forma rápida y fácil. Aquí se
incluye una introducción informal de cómo escribir una aplicación web que utiliza una base de datos con Django.
El objetivo de este documento es darle su ciente información técnica para entender cómo funciona Django, pero no pretende ser un tutorial o referencia - ¡Aunque tenemos ambas
cosas! Cuando esté listo para empezar un proyecto con Django, puede comenzar con el tutorial o: doc:doc:ir directamente a la documentación más detallada </topics/index>.
Diseñe su modelo
Aunque es posible usar Django sin una base de datos, Django cuenta con un mapeador objeto-relacional en el que es posible de nir la estructura de la base de datos utilizando código
Python.
La sintaxis de modelo de datos ofrece muchas formas de representar sus modelos – hasta ahora, ha resuelto una cantidad equivalente a años de problemas de esquemas de base de
datos. Aquí hay un ejemplo rápido:
mysite/news/models.py
class Reporter(models.Model):
full_name = models.CharField(max_length=70)
def __str__(self):
return self.full_name
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
def __str__(self):
return self.headline
Instálelo
Next, run the Django command-line utilities to create the database tables automatically:
/
The makemigrations command looks at all your available models and creates migrations for whichever tables don’t already exist. migrate runs the migrations and creates tables in
your database, as well as optionally providing much richer schema control.
# Save the object into the database. You have to call save() explicitly.
>>> r.save()
# Create an article.
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
... content='Yeah.', reporter=r)
>>> a.save()
# And vice versa: Reporter objects get API access to Article objects.
>>> r.article_set.all()
<QuerySet [<Article: Django is cool>]>
mysite/news/models.py
from django.db import models
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
mysite/news/admin.py
admin.site.register(models.Article)
The philosophy here is that your site is edited by a staff, or a client, or maybe just you – and you don’t want to have to deal with creating backend interfaces only to manage content.
Un ujo de trabajo típico en la creación de aplicaciones Django es crear modelos y poner a funcionar los sitios administrativos lo más rápido posible para que su personal (o clientes)
puedan empezar a ingresar los datos y luego, perfeccionar la forma como los datos se presentan al público.
To design URLs for an app, you create a Python module called a URLconf. A table of contents for your app, it contains a mapping between URL patterns and Python callback functions.
URLconfs also serve to decouple URLs from Python code.
mysite/news/urls.py
urlpatterns = [
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<int:pk>/', views.article_detail),
]
El código anterior mapea las URLs a funciones callback de Python («vistas»). Las cadena de caracteres de la ruta usa etiquetas para «capturar» los valores de las URLs. Cuando un
usuario solicita una página Django pasa por cada patrón en orden y se detiene en el primero que coincide con la URL solicitada. (Si ninguno de ellos coincide Django llama una vista del
caso especial 404). Esto es increíblemente rápido debido a que las rutas son compiladas como expresiones regulares en tiempo de carga.
Una vez que una de las expresiones regulares coincide, Django llama a la vista determinada, que es una función Python. Cada vista recibe un objeto de consulta – que contiene
metadatos de consulta – y los valores capturados en la expresión regular.
Por ejemplo si un usuario solicitara la dirección URL «/articles/2005/05/39323/» Django llamaría la función news.views.article_detail(request, year=2005, month=05,
pk=39323).
Generalmente, una vista recupera los datos de acuerdo con los parámetros, carga una plantilla y crea la plantilla con los datos recuperados. Aquí está una vista de ejemplo para el
year_archive de arriba:
mysite/news/views.py
from django.shortcuts import render
Este ejemplo utiliza el sistema de plantillas de Django que tiene varias características potentes, pero se esfuerza por mantenerse lo su cientemente simple como para que los que no
son programadores lo puedan utilizar.
Django tiene una ruta de búsqueda de plantillas lo que le permite a usted minimizar la redundancia entre las plantillas. En su con guración de Django, usted especi ca una lista de
directorios para veri car si hay plantillas con DIRS. Si una plantilla no existe en el primer directorio, veri ca en el segundo y así sucesivamente.
mysite/news/templates/news/year_archive.html
{% extends "base.html" %}
{% block content %}
<h1>Articles for {{ year }}</h1>
Las variables están rodeadas por llaves dobles. {{ article.headline }} signi ca «Enviar el valor del atributo headline del artículo». Sin embargo, los puntos no sólo se utilizan para
las operaciones de búsqueda de atributo. También pueden hacer búsqueda de pares diccionario-clave, búsqueda de índice y llamadas a funciones.
Tenga en cuenta que {{ article.pub_date|date:"F j, Y" }} utiliza una «tubería» al estilo Unix (el carácter «|»). Esto se conoce como ltro de plantilla, y es una manera de ltrar
el valor de una variable. En este caso, el ltro de fecha formatea un objeto datetime de Python en el formato determinado (como se encuentra en la función de fecha de PHP).
Usted puede encadenar tantos ltros como desee. Usted puede escribir ltros de plantillas personalizados. Usted puede escribir etiquetas de plantillas personalizadas que ejecutan el
código Python personalizado tras bastidores.
Por último, Django usa el concepto de «herencia de plantillas». Eso es lo que hace el {% extends "base.html"%}. Esto quiere decir «Primero cargue la plantilla llamada “base”, que
ha de nido un grupo de bloques, y llene los bloques con los siguientes bloques.» En resumen, eso le permite reducir drásticamente la redundancia en las plantillas: cada plantilla tiene
que de nir sólo lo que es exclusivo de esa plantilla.
Aquí esta la plantilla «base.html», incluyendo el uso de los archivos estáticos de como podría verse:
mysite/templates/base.html
{% load static %}
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<img src="{% static "images/sitelogo.png" %}" alt="Logo">
{% block content %}{% endblock %}
</body>
</html>
Simplistically, it de nes the look-and-feel of the site (with the site’s logo), and provides «holes» for child templates to ll. This means that a site redesign can be done by changing a single
le – the base template.
It also lets you create multiple versions of a site, with different base templates, while reusing child templates. Django’s creators have used this technique to create strikingly different
mobile versions of sites by only creating a new base template.
Tenga en cuenta que usted no tiene que usar el sistema de plantillas de Django si pre ere otro sistema. Si bien el sistema de plantillas de Django está particularmente bien integrado con
la capa modelo de Django, nada lo obliga a usarlo. No tiene tampoco que usar la API de base de datos de Django. Puede usar otra capa de abstracción de base de datos, leer archivos
XML, leer archivos desde el disco o lo que desee. Cada parte de Django – modelos, vistas, plantillas, está separada de la otra.
Guía de instalación rápida
Before you can use Django, you’ll need to get it installed. We have a complete installation guide that covers all the possibilities; this guide will guide you to a minimal installation that’ll
work while you walk through the introduction.
Instale Python
Al ser un framework web de Python, Django requiere del mismo. Consulte ¿Qué versión de Python puedo usar con Django? para más detalles. Python contiene una base de datos ligera
llamada SQLite, por lo que no tendrá que crear una base de datos por el momento.
Obtén la última versión de Python en https://www.python.org/download/ o con el administrador de paquetes de su sistema operativo.
Puede comprobar que Python está instalado escribiendo python desde su shell; debe ver algo como:
Python 3.x.y
[GCC 4.x] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Instale Django
You’ve got three options to install Django:
Instale una versión o cial. Esta es la mejor forma para la mayoría de usuarios.
Instala una versión de Django: doc: proporcionada por la distribución de su sistema operativo <installing-distribution-package>.
Instale la última versión de desarrollo. Esta opción es para los entusiastas que desean las últimas y mejores características y no tienen miedo de ejecutar un código completamente
nuevo. Usted puede encontrarse con nuevos errores en la versión de desarrollo, pero noti carlos ayuda al desarrollo de Django. Además, las versiones de paquetes de terceros
tienen menos probabilidades de ser compatibles con la versión de desarrollo que con la última versión estable.
Si sigue cualquiera de los dos primeros pasos, debe estar pendiente de aquellas partes de la documentación marcadas como nuevo en la versión de desarrollo.
Esa frase indica las características que sólo están disponibles en las versiones de desarrollo de Django, y probablemente no funcionarán con una versión o cial.
Comprobando
Para comprobar que Django puede ser visto por Python, escriba python desde su shell. Luego en el prompt de Python, trate de importar Django:
¡Eso es todo!
Eso es todo - ahora puede pasar al tutorial.
Escribiendo su primera aplicación en Django, parte 1
Aprendamos mediante el ejemplo.
A través de este tutorial le mostraremos cómo crear una aplicación de encuestas básica.
Un sitio público que le permite a las personas ver sondeos y votar en ellos.
Asumiremos que ya ha instalado Django. Puede ver si Django está instalado, así como su versión ejecutando el siguiente comando (señalado por el pre jo $):
/
Si Django está instalado, debería ver la versión de su instalación. Si no es así, obtendrá un error indicando que «No existe el módulo llamado Django».
This tutorial is written for Django 3.1, which supports Python 3.6 and later. If the Django version doesn’t match, you can refer to the tutorial for your version of Django by using the version
switcher at the bottom right corner of this page, or update Django to the newest version. If you’re using an older version of Python, check ¿Qué versión de Python puedo usar con Django?
to nd a compatible version of Django.
Consulte Cómo instalar Django para obtener información sobre cómo desinstalar versiones anteriores de Django e instalar una versión más reciente.
If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.
Creando un proyecto
Si esta es la primera vez que utiliza Django, tendrá que hacerse cargo de ciertas con guraciones iniciales. Concretamente, tendrá que autogenerar un código que establezca un Django
project – un conjunto de ajustes para una instancia de Django, incluida la con guración de la base de datos, opciones especí cas de Django y con guraciones especí cas de la
aplicación.
Desde la línea de comandos, cambie a un directorio donde le gustaría almacenar su código, luego, ejecute el siguiente comando:
/
Esto creará un directorio mysite en su directorio actual. Si no funcionó, consulte Problemas ejecutando django-admin.
Nota
Tendrá que evitar darle nombres a sus proyectos que sean iguales a los de otros componentes integrados de Python o Django. En particular, esto quiere decir que
debe evitar usar nombres como django (que entrará en con icto con Django mismo) o test (que entrará en con icto con un paquete interno de Python).
Si su experiencia previa es con el PHP de siempre (sin haber usado frameworks modernos) probablemente esté acostumbrado a ubicar el código en la raíz del
documento del servidor Web (en un lugar como /var/www). Con Django esto no es así. No es buena idea poner ningún código Python en la raíz del documento
del servidor Web porque existe la posibilidad de que otras personas puedan ver su código en la Web. Eso no es bueno en términos de seguridad.
Introduzca su código en algún directorio fuera del elemento raíz del documento, como por ejemplo /home/mycode.
The outer mysite/ root directory is a container for your project. Its name doesn’t matter to Django; you can rename it to anything you like.
manage.py: Una utilidad de la línea de comandos que le permite interactuar con este proyecto Django de diferentes formas. Puede leer todos los detalles sobre
:archivo:`manage.py` en el :doc: :/ref/django-admin.
En interior del directorio mysite/ es el propio paquete de Python para su proyecto. Su nombre es el nombre del paquete de Python que usted tendrá que utilizar para importar todo
dentro de este (por ejemplo, mysite.urls).
mysite/__init__.py: Un archivo vacío que le indica a Python que este directorio debería ser considerado como un paquete Python. Si usted es un principiante lea más sobre los
paquetes en la documentación o cial de Python.
mysite/settings.py: Ajustes/con guración para este proyecto Django. Django settings le indicará todo sobre cómo funciona la con guración.
mysite/urls.py: Las declaraciones URL para este proyecto Django; una «tabla de contenidos» de su sitio basado en Django. Puede leer más sobre las URLs en URL dispatcher.
mysite/asgi.py: An entry-point for ASGI-compatible web servers to serve your project. See How to deploy with ASGI for more details.
mysite/wsgi.py: Un punto de entrada para que los servidores web compatibles con WSGI puedan servir su proyecto. Consulte :doc:`/howto/deployment/wsgi/index`para más
detalles.
El servidor de desarrollo
Comprobemos que su proyecto Django funciona. Cambie al directorio externo mysite, si todavía no lo ha hecho, y ejecute los siguientes comandos:
/
You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.
Nota
Ignore por ahora la advertencia sobre las migraciones de bases de datos sin aplicar, nos ocuparemos de la base de datos dentro de poco.
Usted ha iniciado el servidor en desarrollo de Django, un servidor web ligero escrito puramente en Python. Lo hemos incluido con Django para que pueda desarrollar cosas rápidamente
sin tener que lidiar con la con guración de un servidor en producción, como Apache, hasta que esté listo para la producción.
Ahora es un buen momento para tener en cuenta que: no debe utilizar este servidor en algo parecido a un entorno de producción. Está pensado sólo para usarse durante el desarrollo
(nuestro trabajo es crear frameworks Web , no servidores web.)
Ahora que el servidor está funcionando, visite http://127.0.0.1:8000/ con su navegador Web. Verá la página «Felicitaciones!», con un cohete despegando. ¡Funcionó!
Cambiando el puerto
De forma predeterminada, el comando runserver inicia el servidor de desarrollo en la IP interna en el puerto 8000.
Si desea cambiar el puerto del servidor, pásalo como un argumento de la línea de comandos. Por ejemplo, este comando inicia el servidor en el puerto 8080:
/
Si desea cambiar la IP del servidor, pásela junto con el puerto. Por ejemplo para escuchar en todas las IPs públicas (útil si usted está ejecutando Vagrant o quiere
mostrar su trabajo en otros equipos de la red), utilice:
/
0 es un atajo para 0.0.0.0. La documentacion completa de el servidor de desarrollo se encuentra en la referencia de runserver.
El servidor de desarrollo recarga de forma automática el código Python para cada petición cuando sea necesario. No es necesario reiniciar el servidor para que los
cambios de código surtan efecto. Sin embargo, algunas acciones como la adición de archivos no provoca un reinicio, por lo que tendrá que reiniciar el servidor en
estos casos.
Cada aplicación que usted escribe en Django consiste en un paquete de Python que sigue una determinada convención. Django tiene una utilidad que genera automáticamente la
estructura básica de directorios de una aplicación, por lo que usted puede centrarse en la escritura de código en lugar de crear directorios.
What’s the difference between a project and an app? An app is a Web application that does something – e.g., a Weblog system, a database of public records or a
small poll app. A project is a collection of con guration and apps for a particular website. A project can contain multiple apps. An app can be in multiple projects.
Your apps can live anywhere on your Python path. In this tutorial, we’ll create our poll app in the same directory as your manage.py le so that it can be imported as its own top-level
module, rather than a submodule of mysite.
Para crear su aplicación, asegúrese de que está en el mismo directorio que el archivo manage.py y escriba este comando:
/
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
polls/views.py
def index(request):
return HttpResponse("Hello, world. You're at the polls index.")
Esta es la vista más simple posible en Django. Para llamar la vista, tenemos que asignarla a una URL y para ello necesitamos una URLconf.
Para crear una URLconf en el directorio encuestas, cree un archivo llamado urls.py. El directorio de su aplicación debe verse así:
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
urls.py
views.py
polls/urls.py
urlpatterns = [
path('', views.index, name='index'),
]
El siguiente paso es señalar la URLconf raíz en el módulo polls.urls. En mysite/urls.py añada un import para django.urls.include e inserte una include() en la lista
urlpatterns , para obtener:
mysite/urls.py
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]
La función include() permite hacer referencia a otros URLconfs. Cada vez que Django encuentra include() corta cualquier parte de la URL que coincide hasta ese punto y envía la
cadena restante a la URLconf incluida para seguir el proceso.
La idea detrás de include() es facilitar la conexión y ejecución inmediata de las URLs. Dado que las encuestas están en su propia URLconf (polls/urls.py) se pueden ubicar en
«/polls/», «/fun_polls /», «/content/polls/» o en cualquier otra ruta raíz , y la aplicación todavía seguirá funcionando.
Siempre debe usar include() cuando incluye otros patrones de URL. admin.site.urls es la única excepción a esto.
You have now wired an index view into the URLconf. Verify it’s working with the following command:
/
$ python manage.py runserver
Vaya a http://localhost:8000/polls/ en su navegador, y usted debería ver el texto «Hello, world. You’re at the polls index.» el cual de nió en la vista index.
¿Página no encotrada?
Si usted obtiene aquí una página de error, revisee que usted este llendo a la dirección URL http://localhost:8000/polls/ y no a la dirección URL
http://localhost:8000/.
La path() función recibe cuatro argumentos, dos requeridos route y view; y dos opcionales kwargs y name. Este es el momento de revisar para que sirven estos argumentos.
Tenga en cuenta que estas expresiones regulares no buscan parámetros GET y POST o el nombre de dominio. Por ejemplo en una petición a la dirección URL
https://www.example.com/myapp/, la URLconf buscará myapp/. En una petición a https://www.example.com/myapp/?page=3 la URLconf también buscará myapp/.
Cuando se familiarice con el ujo básico de solicitud y respuesta, lea la parte 2 del presente tutorial para empezar a trabajar con la base de datos.
Escribiendo su primera aplicación en Django, parte 2
Este tutorial comienza donde quedó el Tutorial 1. Vamos a con gurar la base de datos, crear su primer modelo y recibir una introducción rápida al sitio administrativo generado
automáticamente de Django.
If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.
Por defecto la con guración utiliza SQLite. Si tiene poca experiencia con bases de datos o su interés es solo probar Django esta es la opción más fácil. SQLite está incluido en Python por
lo que no tendrá que instalar nada más para soportar su base de datos. Sin embargo, al iniciar su primer proyecto real, es posible que desee utilizar una base de datos más potente como
PostgreSQL para evitar dolores de cabeza en el futuro al tener que cambiar entre base de datos.
Si desea utilizar otra base de datos, instale los conectores de base de datos apropiados, y cambie las siguientes claves en el ítem DATABASES 'default' para que se ajusten a la
con guración de conexión de la base de datos:
NAME – The name of your database. If you’re using SQLite, the database will be a le on your computer; in that case, NAME should be the full absolute path, including lename, of that
le. The default value, BASE_DIR / 'db.sqlite3', will store the le in your project directory.
Si no está utilizando SQLite como su base de datos, se deben añadir ajustes adicionales tales como USER, PASSWORD, y HOST se deben añadir. Para más información, vea la
documentación de referencia para DATABASES.
Si está utilizando una base de datos SQLite, asegúrese de que ha creado ya la base de datos en este punto. Hágalo con el comando «CREATE DATABASE
database_name;» en la consola interactiva de la base de datos.
Del mismo modo asegúrese de que la base de datos proporcionada en el archivo mysite/settings.py tiene permisos de tipo «create database». Esto permitirá
la creación automática de test database que será necesaria en un tutorial posterior.
Si estás usando SQLite, no es necesario crear nada de antemano - el archivo de base de datos se creará automáticamente cuando sea necesario.
Mientras que usted está editando el archivo mysite/settings.py, con gure TIME_ZONE a su zona horaria.
Además, observe que la con guración de INSTALLED_APPS se encuentra en la parte superior del archivo. Esta contiene los nombres de todas las aplicaciones Django que están
activadas en esta instancia de Django. Las aplicaciones se pueden usar en diversos proyectos y usted puede empaquetar y distribuirlas para que otras personas las puedan utilizar en
sus proyectos.
Por defecto, INSTALLED_APPS contiene las siguientes aplicaciones y Django viene equipado con todas ellas:
Estas aplicaciones se incluyen de forma predeterminada como una conveniencia para el caso común.
Algunas de estas aplicaciones utilizan al menos una tabla de base de datos, por lo que necesitamos crear las tablas en la base de datos antes de poder utilizarlas. Para ello, ejecute el
siguiente comando:
/
The migrate command looks at the INSTALLED_APPS setting and creates any necessary database tables according to the database settings in your mysite/settings.py le and
the database migrations shipped with the app (we’ll cover those later). You’ll see a message for each migration it applies. If you’re interested, run the command-line client for your
database and type \dt (PostgreSQL), SHOW TABLES; (MariaDB, MySQL), .schema (SQLite), or SELECT TABLE_NAME FROM USER_TABLES; (Oracle) to display the tables Django
created.
Como dijimos anteriormente, las aplicaciones predeterminadas se incluyen para el caso común, pero no todos las necesitan. Si usted no necesita alguna o
ninguna de ellas, no dude en dejar fuera o borrar las línea(s) correspondientes desde INSTALLED_APPS antes de ejecutar el comando migrate. El comando
migrate solo ejecutará migraciones para aplicaciones en INSTALLED_APPS.
Creando modelos
A continuación de niremos sus modelos, sobre todo su estructura de base de datos, con metadatos adicionales.
Filosofía
Un modelo es la fuente única y de nitiva de información sobre sus datos. Contiene los campos esenciales y los comportamientos de los datos que usted guarda.
Django sigue el Principio DRY. El objetivo es de nir el modelo de datos en un solo lugar y derivar cosas de este automáticamente.
This includes the migrations - unlike in Ruby On Rails, for example, migrations are entirely derived from your models le, and are essentially a history that Django
can roll through to update your database schema to match your current models.
In our poll app, we’ll create two models: Question and Choice. A Question has a question and a publication date. A Choice has two elds: the text of the choice and a vote tally. Each
Choice is associated with a Question.
These concepts are represented by Python classes. Edit the polls/models.py le so it looks like this:
polls/models.py
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
Here, each model is represented by a class that subclasses django.db.models.Model. Each model has a number of class variables, each of which represents a database eld in the
model.
Cada campo está representado por una instancia de una clase Field, por ejemplo, CharField para campos de caracteres y DateTimeField para variables de tiempo y fecha. Esto le
dice a Django qué tipo de datos cada campo contiene.
El nombre de cada instancia Field (por ejemplo, question_text o pub_date)` es el nombre del campo, en formato adaptado al lenguaje de la máquina. Va a usar este valor en el
código Python y su base de datos va a usarlo como el nombre de la columna.
Puede emplear un primer argumento posicional opcional a una Field para designar un nombre legible por humanos. Ese se utiliza en varias partes introspectivas de Django y sirve al
mismo tiempo como documentación. Si no se proporciona este campo, Django usará el nombre legible por la máquina. En este ejemplo, sólo hemos de nido un nombre legible para
Question.pub_date. Para el resto de los campos en este modelo, el nombre del campo legible por la máquina servirá como el nombre legible por humanos.
Algunas clases Field precisan argumentos. La clase CharField, por ejemplo, requiere que usted le asigne un max_length. Esta se utiliza no sólo en el esquema de la base de datos,
sino también en la validación como veremos dentro de poco.
Una clase Field también puede tener varios argumentos opcionales; en este caso, le hemos jado al default el valor de votes en 0.
Por último, tenga en cuenta que una relación se de ne usando ForeignKey. Eso le indica a Django que cada Choice se relaciona con un sola Question. Django es compatible con
todas las relaciones de bases de datos comunes: varias a una, varias a varias y una a una.
Crear un esquema de base de datos para esta aplicación (oraciones CREATE TABLE).
Crear una API de acceso a la base datos Python para acceder a los objetos Question y Choice.
Pero primero tenemos que indicarle a nuestro proyecto que la aplicación polls está instalada.
Filosofía
Las aplicaciones Django son «conectables»: Usted puede utilizar una aplicación en diversos proyectos y puede distribuir aplicaciones porque ellas no necesitan
estar atadas a una determinada instalación de Django.
Para incluir la aplicación en nuestro proyecto necesitamos agregar una referencia a su clase de con guración en la con guración INSTALLED_APPS. La clase PollsConfig está en el
archivo polls/apps.py por lo que su ruta punteada es 'polls.apps.PollsConfig'. Edite el archivo mysite/settings.py y agregue la ruta punteada a la con guración
INSTALLED_APPS. Se verá así:
mysite/settings.py
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
Ahora Django sabe incluir la aplicación polls. Vamos a ejecutar otro comando:
/
Al ejecutar makemigrations, usted le indica a Django que ha realizado algunos cambios a sus modelos (en este caso, ha realizado cambios nuevos) y que le gustaría que los guarde
como una migración.
Migrations are how Django stores changes to your models (and thus your database schema) - they’re les on disk. You can read the migration for your new model if you like; it’s the le
polls/migrations/0001_initial.py. Don’t worry, you’re not expected to read them every time Django makes one, but they’re designed to be human-editable in case you want to
manually tweak how Django changes things.
Hay un comando que ejecutará las migraciones para usted y gestionará el esquema de base de datos automáticamente; este se denomina migrate, y hablaremos de ello en un
momento, pero primero, vamos a ver cuál SQL esa migración ejecutaría . El comando sqlmigrate recibe nombres de migración y devuelve su SQL:
/
Debería ver algo similar a lo siguiente (lo hemos reformateado para facilitar la lectura):
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" (
"id" serial NOT NULL PRIMARY KEY,
"question_text" varchar(200) NOT NULL,
"pub_date" timestamp with time zone NOT NULL
);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
"id" serial NOT NULL PRIMARY KEY,
"choice_text" varchar(200) NOT NULL,
"votes" integer NOT NULL,
"question_id" integer NOT NULL
);
ALTER TABLE "polls_choice"
ADD CONSTRAINT "polls_choice_question_id_c5b4b260_fk_polls_question_id"
FOREIGN KEY ("question_id")
REFERENCES "polls_question" ("id")
DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");
COMMIT;
La salida exacta variará dependiendo de la base de datos que esté utilizando. El ejemplo anterior se genera para PostgreSQL.
Los nombres de las tablas se generan automáticamente combinando el nombre de la aplicación (polls) y el nombre del modelo en minúscula; question y choice. (Usted puede
anular este comportamiento)
Las claves primarias (IDs) se agregan automáticamente. (Usted también puede anular esto)
Convencionalmente, Django añade "_id" al nombre del campo de la clave externa (sí, usted también puede anular esto)
The foreign key relationship is made explicit by a FOREIGN KEY constraint. Don’t worry about the DEFERRABLE parts; it’s telling PostgreSQL to not enforce the foreign key until the
end of the transaction.
Se adapta a la base de datos que está utilizando, así que los tipos de campos especí cos de la bases de datos como auto_increment (MySQL), serial (PostgreSQL) o
integer primary key autoincrement (SQLite) se gestionan de forma automática. Lo mismo se aplica para la cita de nombres de campos, por ejemplo, el uso de comillas
dobles o comillas simples.
The sqlmigrate command doesn’t actually run the migration on your database - instead, it prints it to the screen so that you can see what SQL Django thinks is required. It’s useful
for checking what Django is going to do or if you have database administrators who require SQL scripts for changes.
Si le interesa, usted también puede ejecutar el comando python manage.py check; este revisa cualquier problema en su proyecto sin hacer migraciones o modi car la base de datos.
A continuación, ejecute de nuevo el comando migrate para crear esas tablas modelos en su base de datos:
/
El comando migrate toma todas las migraciones que no han sido aplicadas (Django rastrea cuales se aplican utilizando una tabla especial en su base de datos llamada
django_migrations) y las ejecuta contra su base de datos; básicamente, sincronizando los cambios que usted ha realizado a sus modelos con el esquema en la base de datos.
Las migraciones son muy potentes y le permiten modi car sus modelos con el tiempo, a medida que desarrolla su proyecto, sin necesidad de eliminar su base de datos o las tablas y
hacer otras nuevas. Este se especializa en la actualización de su base de datos en vivo, sin perder datos. Vamos a hablar de ellas en mayor profundidad más tarde en el tutorial, pero por
ahora, recuerde la guía de tres pasos para hacer cambios de modelo:
Ejecute el comando python manage.py makemigrations para crear migraciones para esos cambios
Ejecute el comando python manage.py migrate para aplicar esos cambios a la base de datos.
The reason that there are separate commands to make and apply migrations is because you’ll commit migrations to your version control system and ship them with your app; they not
only make your development easier, they’re also usable by other developers and in production.
Lea la documentación del django-admin para obtener información detallada sobre lo que puede hacer la utilidad manage.py.
Jugando con la API
Ahora vayamos al shell interactivo de Python y juguemos con la API gratuita que Django le proporciona. Para llamar el shell de Python, utilice este comando:
/
We’re using this instead of simply typing «python», because manage.py sets the DJANGO_SETTINGS_MODULE environment variable, which gives Django the Python import path to your
mysite/settings.py le.
>>> from polls.models import Choice, Question # Import the model classes we just wrote.
# Save the object into the database. You have to call save() explicitly.
>>> q.save()
Un segundo. <Question: Question object (1)> no es una representación útil de este objeto. Arreglemos esto modi cando el modelo Question (en el archivo
polls/models.py) y agregando un metodo __str__() a los dos modelos, Question y Choice:
polls/models.py
class Question(models.Model):
# ...
def __str__(self):
return self.question_text
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text
Es importante añadir los métodos __str__() a sus modelos, no solo para su conveniencia al lidiar con la línea de comandos interactiva, sino también porque las representaciones de
objetos se usan en todo el sitio administrativo generado automáticamente de Django.
polls/models.py
import datetime
class Question(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
Tenga en cuenta la adición de import datetime y from django.utils import timezone, para hacer referencia el módulo estándar de Python datetime y las herramientas
relacionadas con el huso horario de Django django.utils.timezone respectivamente. Si usted no está familiarizado con el manejo de la zona horaria en Python, usted puede
aprender más en la documentación de soporte de zona horaria.
Guarde estos cambios e inicie un nuevo shell interactivo Python ejecutando de nuevo python manage.py shell:
>>> from polls.models import Choice, Question
# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)
# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
<QuerySet []>
Para obtener más información sobre las relaciones de modelos, consulte Accediendo a objetos relacionados. Para más información sobre cómo utilizar guiones bajos para realizar
búsquedas de campo a través de la API, consulte :ref: Búsquedas de campos < eld-lookups-intro>. Para más detalles sobre la API de base de datos, consulte nuestra Referencia de API
de base de datos.
Presentando el sitio administrativo de Django
Filosofía
La generación de sitios administrativos para su personal o clientes para agregar, modi car y eliminar contenido es un trabajo aburrido que no requiere mucha
creatividad. Por esa razón, Django automatiza completamente la creación de interfaces de sitios administrativos para los modelos.
Django fue escrito en un entorno de sala de redacción, con una separación muy clara entre «los editores de contenido» y el sitio «público». Los administradores del
sitio utilizan el sistema para agregar noticias, eventos, resultados deportivos, etc., y ese contenido se muestra en el sitio público. Django resuelve el problema de
crear una interfaz uni cada para los administradores del sitio para editar el contenido.
El sitio admin no está destinado a ser utilizado por los visitantes del sitio. Es para los administradores del sitio.
/
Username: admin
El paso nal es introducir su contraseña. Se le pedirá que introduzca su contraseña dos veces, la segunda vez como con rmación de la primera.
Password: **********
Password (again): *********
Superuser created successfully.
/
A continuación, abra un navegador Web y vaya a «/admin/» en su dominio local, por ejemplo, http://127.0.0.1:8000/admin/. Usted debe ver la pantalla de inicio de sesión del sitio
administrativo:
Since translation is turned on by default, if you set LANGUAGE_CODE, the login screen will be displayed in the given language (if Django has appropriate translations).
Usted debería ver algunos tipos de contenidos editables: grupos y usuarios. Ellos son proporcionados por django.contrib.auth, el framework de autenticación enviado por Django.
Only one more thing to do: we need to tell the admin that Question objects have an admin interface. To do this, open the polls/admin.py le, and edit it to look like this:
polls/admin.py
admin.site.register(Question)
Los diferentes tipos de campos del modelo (DateTimeField, CharField) corresponden al widget de entrada HTML adecuado. Cada tipo de campo sabe cómo mostrarse en el
sitio administrativo de Django.
Cada DateTimeField tiene atajos de JavaScript sin restricciónes. Las fechas tienen un atajo «Hoy» y una ventana emergente del calendario, mientras que las horas tienen un atajo
«Ahora» y una ventana emergente conveniente que enumera las horas que se registran comúnmente.
Guardar – Guarda los cambios y retorna a la página de la lista de cambios para este tipo de objeto.
Guardar y continuar editando – Guarda los cambios y recarga la página del sitio administrativo para este objeto.
Guardar y añadir otro – Guarda los cambios y carga un nuevo formulario vacio para este tipo de objeto.
Si el valor de «Date published» no coincide con la hora en la que creó la pregunta en el Tutorial 1, probablemente signi ca que se olvidó de establecer el valor correcto para la
con guración de TIME_ZONE. Modifíquelo, recargue la página y compruebe que aparezca el valor correcto.
Modi que la «Date published» haciendo clic en los atajos «Hoy» y «Ahora». Después, haga clic en «Guardar y continuar editando». Luego haga clic en «Historial» en la parte superior
derecha. Usted verá una página que enumera todos los cambios realizados a este objeto a través del sitio administrativo de Django, con el registro de tiempo y el nombre de usuario de la
persona que realizó el cambio:
Cuando se sienta cómodo con la API de modelos y se haya familiarizado con el sitio administrativo, lea la parte 3 de este tutorial para aprender sobre cómo agregar más vistas a nuestra
aplicación encuestas.
Escribiendo su primera aplicación en Django, parte 3
Este tutorial comienza donde quedó el Tutorial 2. Vamos a continuar con la aplicación Web para encuestas y vamos a enfocarnos en crear la interfaz pública –»vistas»
If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.
Información general
Una vista es un «tipo» de página Web de su aplicación Django, que generalmente cumple una función especí ca y tiene una plantilla especí ca. Por ejemplo, en una aplicación de blog,
usted puede tener las siguientes vistas:
Página de entrada de «detail» – página de enlace permanente para una entrada individual.
Página de archivo basado en el año – muestra todos los meses con entradas en un año determinado.
Página de archivo basado en el mes – muestra todos los días con las entradas en un mes determinado.
Página de archivo basado en el día – muestra todas las entradas de un día determinado.
La página «de detalle» de preguntas– muestra un texto de pregunta sin resultados, pero con un formulario para votar.
Votar – gestiona la votación para una elección concreta en una pregunta especí ca.
In Django, web pages and other content are delivered by views. Each view is represented by a Python function (or method, in the case of class-based views). Django will choose a view by
examining the URL that’s requested (to be precise, the part of the URL after the domain name).
Now in your time on the web you may have come across such beauties as ME2/Sites/dirmod.htm?sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B. You
will be pleased to know that Django allows us much more elegant URL patterns than that.
Para llegar desde una URL a una vista Django usa lo que se conoce como “URLconfs”. Una URLconf mapea patrones de URL a vistas.
Este tutorial proporciona instrucción básica en el uso de URLconfs. Usted puede consultar URL dispatcher para más información.
polls/views.py
Una estas nuevas vistas al módulo polls.urls añadiendo las siguientes llamadas path():
polls/urls.py
from django.urls import path
urlpatterns = [
# ex: /polls/
path('', views.index, name='index'),
# ex: /polls/5/
path('<int:question_id>/', views.detail, name='detail'),
# ex: /polls/5/results/
path('<int:question_id>/results/', views.results, name='results'),
# ex: /polls/5/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
]
Eche un vistazo en su navegador a «/polls/34/». Va a ejecutar el método detail() y mostrar cualquier ID que usted suministre en la URL. Pruebe «/polls/34/results/» y también
«/polls/34/vote/» - estas mostrarán los resultados del marcador de posición y las páginas de votación.
Cuando alguien solicita una página desde su sitio web - digamos, «/polls/34/», Django cargará el módulo Python mysite.urls porque está señalado por la con guración
ROOT_URLCONF. Él encuentra la variable llamada urlpatterns y recorre las expresiones regulares en orden. Cuando encuentra la coincidencia 'polls/' retira el texto que coincide
("polls/") y envía el texto restante - "34/" - a la URLconf “polls.urls” para seguir siendo procesado. Allí la coincidencia '<int:question_id>/' resulta en una llamada a la vista
detail() de la siguiente forma:
La parte question_id='34' proviene de <int:question_id>. Utilizando paréntesis en torno a un patrón «captura» parte de la URL y lo envía como un argumento de palabra clave a
la función de vista. La parte :question_id> de la cadena de ne el nombre que se utilizará para identi car el patrón buscado y la parte <int: es un convertidor que determina que
patrones podrían coincidir con esta parte de la ruta de la URL.
Su vista puede leer registros de una base de datos o no, puede usar un sistema de plantillas como el de Django o un sistema de plantillas Python de terceros o no. Puede generar un
archivo PDF, salida XML, crear un archivo ZIP en la marcha, todo lo que quiera, utilizando cualquier librería de Python que desee.
Debido a que es conveniente, vamos a utilizar la propia API de base de datos de Django, que estudiamos en el Tutorial 2. A continuación señalaremos una nueva vista index() que
muestra en el sistema las 5 últimas preguntas de la encuesta, separadas por comas, según su fecha de publicación:
polls/views.py
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
output = ', '.join([q.question_text for q in latest_question_list])
return HttpResponse(output)
Sin embargo, aquí hay un problema: el diseño de la página está codi cado de forma ja en la vista. Si desea cambiar la forma en que se ve la página, tendrá que editar el código Python.
Así que vamos a usar el sistema de plantillas de Django para separar el diseño de Python mediante la creación de una plantilla que la vista pueda utilizar.
Primero, cree un directorio llamado templates en su directorio polls. Django buscará las plantillas allí.
La con guración de TEMPLATES de su proyecto describe cómo Django cargará y creará las plantillas. El archivo de con guración predeterminada con gura un backend
DjangoTemplates cuya opción APP_DIRS está con gurada como True. Convencionalmente, DjangoTemplates busca un subdirectorio «templates» en cada una de las
INSTALLED_APPS.
Within the templates directory you have just created, create another directory called polls, and within that create a le called index.html. In other words, your template should be at
polls/templates/polls/index.html. Because of how the app_directories template loader works as described above, you can refer to this template within Django as
polls/index.html.
Espacio de nombres de plantillas
Now we might be able to get away with putting our templates directly in polls/templates (rather than creating another polls subdirectory), but it would
actually be a bad idea. Django will choose the rst template it nds whose name matches, and if you had a template with the same name in a different application,
Django would be unable to distinguish between them. We need to be able to point Django at the right one, and the best way to ensure this is by namespacing them.
That is, by putting those templates inside another directory named for the application itself.
polls/templates/polls/index.html
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
Nota
To make the tutorial shorter, all template examples use incomplete HTML. In your own projects you should use complete HTML documents.
Ahora vamos a actualizar nuestra vista index en polls/views.py para usar la plantilla:
polls/views.py
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
template = loader.get_template('polls/index.html')
context = {
'latest_question_list': latest_question_list,
}
return HttpResponse(template.render(context, request))
Ese código carga la plantilla llamada polls/index.html y le pasa un contexto. El contexto es un diccionario que relaciona los nombres de variables de plantillas con objetos Python.
Cargue la página señalando su navegador en «/polls/», y usted debería ver una lista con viñetas que contiene la pregunta «¿Qué pasa?» del Tutorial 2. El enlace señala la página de
detalles de la pregunta.
Un atajo: render()
Es una práctica muy común cargar una plantilla, llenar un contexto y retornar un objeto HttpResponse con el resultado de la plantilla creada. Django proporciona un atajo. A
continuación la vista index() completa, reescrita:
polls/views.py
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
Tenga en cuenta que una vez que hemos hecho esto en todas estas vistas, ya no necesitamos importar loader y HttpResponse (usted querrá continuar HttpResponse si usted
todavía tiene los métodos stub para detail, results y vote).
La función render() toma el objeto solicitado como su primer argumento, un nombre de plantilla como su segundo argumento y un diccionario como su tercer argumento opcional. La
función retorna un objeto HttpResponse de la plantilla determinada creada con el contexto dado.
polls/views.py
El nuevo concepto aquí: La vista levanta la excepción Http404 si no existe una pregunta con la ID solicitada.
Hablaremos de lo que podría poner en esa plantilla polls/detail.html un poco más tarde, pero si desea empezar a trabajar con el ejemplo anterior, un archivo que contenga
simplemente:
polls/templates/polls/detail.html
{{ question }}
Un atajo get_object_or_404()
Es una práctica muy común utilizar get() y levantar la excepción Http404 si no existe el objeto. Django proporciona un atajo. Aquí está la vista detail(), reescrita:
polls/views.py
La función get_object_or_404() toma un modelo Django como su primer argumento y un número arbitrario de argumentos de palabra clave que pasa a la función get() del
administrador del modelo. Levanta la excepción Http404 si no existe el objeto.
Filosofía
¿Por qué utilizamos una función auxiliar get_object_or_404() en lugar de capturar las excepciones ObjectDoesNotExist en un nivel superior, o hacer que
la API del modelo levante la excepción Http404 en vez de la excepción ObjectDoesNotExist?
Porque eso acoplaría la capa de modelos con la capa de vistas. Uno de los objetivos de diseño más destacados de Django es mantener el bajo acoplamiento.
Algo de acoplamiento controlado se introduce en el módulo django.shortcuts.
También hay una función get_list_or_404() , que funciona igual que get_object_or_404() - excepto usando filter() en lugar de get(). La misma levanta la excepción
Http404 si la lista está vacía.
Utilice el sistema de plantillas
Vuelva a la vista detail() para nuestra aplicación encuesta. Teniendo en cuenta la variable de contexto question, así es como la plantilla polls/detail.html podría verse:
polls/templates/polls/detail.html
El sistema de plantillas utiliza la sintaxis de búsqueda con puntos para acceder a los atributos de variables. En el ejemplo de {{question.question_text}}, Django primero realiza
una consulta en el diccionario sobre el objeto question. Si esto falla, intenta una búsqueda de atributos que en este caso funciona. Si la búsqueda de atributos hubiera fallado, hubiera
intentado una búsqueda de índice de lista.
El llamado del método ocurre en el bucle {% for%}: question.choice_set.all se interpreta como el código Python question.choice_set.all() que retorna un iterable de
objetos Choice y es adecuado para usarse en la etiqueta {% for%}.
El problema con este método de codi cación predeterminada y estrechamente acoplada es que se hace difícil modi car las URLs en proyectos que tengan muchas plantillas. Sin
embargo, puesto que usted de nió el argumento de nombre en las funciones path() en el módulo polls.urls, usted puede eliminar la dependencia en rutas URL especí cas de nida
en su con guración de URL usando la etiqueta de plantilla {% url %}:
La forma como esto funciona es buscando la de nición de la URL como se especí ca en el módulo polls.urls. Usted puede ver exactamente donde se de ne el nombre de la URL de
“detail” a continuación:
...
# the 'name' value as called by the {% url %} template tag
path('<int:question_id>/', views.detail, name='detail'),
...
Si desea modi car la URL de la vista de detalle de las encuestas a algo diferente, quizás a algo como polls/specifics/12/, en lugar de hacerlo en la plantilla (o plantillas), usted la
modi caría en polls/urls.py:
...
# added the word 'specifics'
path('specifics/<int:question_id>/', views.detail, name='detail'),
...
polls/urls.py
app_name = 'polls'
urlpatterns = [
path('', views.index, name='index'),
path('<int:question_id>/', views.detail, name='detail'),
path('<int:question_id>/results/', views.results, name='results'),
path('<int:question_id>/vote/', views.vote, name='vote'),
]
polls/templates/polls/index.html
polls/templates/polls/index.html
When you’re comfortable with writing views, read part 4 of this tutorial to learn the basics about form processing and generic views.
Escribiendo su primera aplicación en Django, parte 4
This tutorial begins where Tutorial 3 left off. We’re continuing the Web-poll application and will focus on form processing and cutting down our code.
If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.
polls/templates/polls/detail.html
Un resumen rápido:
La plantilla anterior muestra un botón de opción para cada pregunta de selección. El value de cada botón de opción es la ID de la pregunta de selección asociada. El name de cada
botón de opción es "choice". Esto signi ca que cuando alguien selecciona uno de los botones de opción y envía el formulario, enviará los datos POST choice=# donde # es la ID
de la opción seleccionada. Este es el concepto básico de los formularios HTML.
We set the form’s action to {% url 'polls:vote' question.id %}, and we set method="post". Using method="post" (as opposed to method="get") is very
important, because the act of submitting this form will alter data server-side. Whenever you create a form that alters data server-side, use method="post". This tip isn’t speci c to
Django; it’s good Web development practice in general.
Since we’re creating a POST form (which can have the effect of modifying data), we need to worry about Cross Site Request Forgeries. Thankfully, you don’t have to worry too hard,
because Django comes with a helpful system for protecting against it. In short, all POST forms that are targeted at internal URLs should use the {% csrf_token %} template tag.
A continuación, vamos a crear una vista Django que maneje los datos enviados y haga algo con ello. Recuerde que en el Tutorial 3, creamos un URLconf para la aplicación encuestas que
incluye esta línea:
polls/urls.py
También creamos una implementación simulada de la función vote(). Vamos a crear una versión real. Agregue lo siguiente a polls/views.py:
polls/views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
Este código incluye algunas cosas que no hemos cubierto todavía en este tutorial:
request.POST es un objeto tipo diccionario que le permite acceder a los datos presentados mediante el nombre clave. En este caso, request.POST['choice'] retorna la ID de
la opción seleccionada como una cadena. Los valores request.POST son siempre cadenas.
Tenga en cuenta que Django también proporciona request.GET para acceder a datos GET de la misma manera, pero estamos usando de manera explícita request.POST en
nuestro código, para garantizar que los datos sólo se modi quen a través de una llamada POST.
request.POST['choice'] levantará un excepción :exc: KeyError si choice no fue proporcionado en los datos POST. El código anterior busca la excepción KeyError y muestra
de nuevo el formulario de pregunta con un mensaje de error si no se ha proporcionado choice.
Después de incrementar el conteo de la elección, el código retorna una HttpResponseRedirect en lugar de una HttpResponse normal HttpResponseRedirect toma un
único argumento: La URL a la que el usuario será redirigido (vea el siguiente aspecto de cómo construimos la URL en este caso).
As the Python comment above points out, you should always return an HttpResponseRedirect after successfully dealing with POST data. This tip isn’t speci c to Django; it’s
good Web development practice in general.
Estamos utilizando la función reverse() en el constructor HttpResponseRedirect en este ejemplo. Esta función ayuda a evitar tener que codi car una URL en la función de
vista. Se proporciona el nombre de la vista a la que queremos pasar el control y la parte de la variable del patrón de URL que señala esa vista. En este caso, utilizando la URLconf
que con guramos en el Tutorial 3, esta llamada reverse() retornará una cadena como
'/polls/3/results/'
donde el 3 es el valor de question.id. Esta URL redirigida entonces llamará a la vista 'results' para mostrar la página nal.
Como se mencionó en el Tutorial 3, request es un objeto HttpRequest . Para más información sobre los objetos HttpRequest, consulte la documentación de petición y respuesta.
Después de que alguien vota en una pregunta, la vista vote() remite a la página de resultados de la pregunta. Vamos a escribir dicha vista:
polls/views.py
Esto es casi exactamente lo mismo que la vista detail() del Tutorial 3. La única diferencia es el nombre de la plantilla. Solucionaremos esta redundancia más tarde.
polls/templates/polls/results.html
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
A continuación, vaya a /polls/1/ en su navegador y vote en la pregunta. Debería ver una página de resultados que se actualiza cada vez que usted vota. Si usted envía el formulario sin
haber seleccionado una opción, usted debería ver el mensaje de error.
Nota
El código para nuestra vista vote() tiene un pequeño problema. Primero, obtiene el objeto selected_choice de la base de datos, luego, calcula el nuevo valor
de votes, y después lo guarda de nuevo en la base de datos. Si dos usuarios de su sitio Web intentan votar exactamente en el mismo momento, esto podría salir
mal: El mismo valor, digamos 42, será recuperado para votes. Entonces, se calcula y se guarda el nuevo valor de 43 para ambos usuarios, pero el 44 sería el valor
esperado.
Esto se conoce como una condición de carrera. Si usted está interesado, puede leer :ref: avoiding-race-conditions-using-f para aprender cómo solucionar este
problema.
Estas vistas representan un caso común de desarrollo Web básico: obtener datos de la base de datos según un parámetro pasado en la URL, cargar una plantilla y retornar la plantilla
creada. Debido a que esto es tan común, Django proporciona un atajo denominado sistema de «vistas genéricas».
Las vistas genéricas abstraen los patrones comunes hasta el punto en que ni siquiera es necesario escribir código Python para escribir una aplicación.
Let’s convert our poll app to use the generic views system, so we can delete a bunch of our own code. We’ll have to take a few steps to make the conversion. We will:
1. Convertir el URLconf.
Generalmente, cuando se escribe una aplicación de Django, usted podrá evaluar si las vistas genéricas son una buena opción para su problema y las utilizará
desde el principio en lugar de reestructurar su código a medio camino. Sin embargo, este tutorial intencionadamente se ha centrado hasta ahora en escribir las
vistas «de la manera difícil» para centrarse en los conceptos esenciales.
polls/urls.py
app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
path('<int:question_id>/vote/', views.vote, name='vote'),
]
Tenga en cuenta que el nombre del patrón coincidente en las cadenas de ruta de los patrones segundo y tercero ha cambiado de <question_id> a <pk>.
polls/views.py
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
"""Return the last five published questions."""
return Question.objects.order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'
class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html'
Estamos utilizando dos vistas genéricas aquí: ListView y DetailView. Respectivamente, esas dos vistas abstraen los conceptos de «mostrar una lista de objetos» y «mostrar una
página de detalles para un tipo especí co de objeto.»
Cada vista genérica tiene que saber cuál es el modelo sobre el que estará actuando. Esto se proporciona utilizando el atributo model.
La vista genérica DetailView espera que el valor de la clave primaria capturado desde la URL sea denominado "pk", por lo que hemos cambiado``question_id`` a pk para las
vistas genéricas.
Por defecto, la vista genérica DetailView utiliza una plantilla llamada <app name>/<model name>_detail.html. En nuestro caso, utilizaría la plantilla
"polls/question_detail.html". El atributo template_name se utiliza para indicarle a Django que utilice un nombre de plantilla especí co en vez del nombre de plantilla generado
de forma automática. También especi camos el atributo template_name para la vista de lista results, esto garantiza que la vista de resultados y la vista detalle tengan un aspecto
diferente cuando sean creadas, a pesar de que las dos son una vista genérica DetailView en segundo plano.
Del mismo modo, la vista genérica ListView utiliza una plantilla predeterminada llamada <app name>/<model name>_list.html; utilizamos el atributo template_name para
indicarle a ListView que utilice nuestra plantilla "polls/index.html" existente.
In previous parts of the tutorial, the templates have been provided with a context that contains the question and latest_question_list context variables. For DetailView the
question variable is provided automatically – since we’re using a Django model (Question), Django is able to determine an appropriate name for the context variable. However, for
ListView, the automatically generated context variable is question_list. To override this we provide the context_object_name attribute, specifying that we want to use
latest_question_list instead. As an alternative approach, you could change your templates to match the new default context variables – but it’s a lot easier to tell Django to use the
variable you want.
Ejecute el servidor y utilice su nueva aplicación encuesta basada en las vistas genéricas.
Para más detalles sobre las vistas genéricas, consulte la documentación de las vistas genéricas.
Cuando esté familiarizado con los formularios y las vistas genéricas, lea la parte 5 de este tutorial para aprender sobre cómo probar nuestra aplicación encuestas.
Escribiendo su primera aplicación en Django, parte 5
Este tutorial comienza donde quedó el Tutorial 4. Hemos creado una aplicación Web de encuestas y ahora vamos a crear algunas pruebas automatizadas para ella.
If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.
Las pruebas se ejecutan en diferentes niveles. Algunas pruebas se pueden aplicar a un pequeño detalle (¿Un método de modelo particular retorna valores como se espera?) mientras que
otras examinan el total funcionamiento del software (¿Una secuencia de entradas de usuarios en el sitio produce el resultado deseado?). No se diferencia del tipo de pruebas que ejecutó
anteriormente en el Tutorial 2 utilizando el comando shell para examinar el comportamiento de un método, o ejecutar la aplicación e ingresar datos para comprobar cómo se
comporta.
Lo que es diferente en las pruebas automatizadas es que el trabajo de pruebas por usted lo hace el sistema. Usted crea un conjunto de pruebas una vez, después, a medida que modi ca
su aplicación, puede comprobar que el código todavía funciona como originalmente lo concibió, sin necesidad de pruebas manuales engorrosas.
Usted podría pensar que ya con aprender Python y Django tiene bastante con qué ocuparse, y que tener que aprender y hacer aún más cosas podría ser abrumador y hasta innecesario.
Después de todo, nuestra aplicación encuestas está funcionando ahora bastante bien, tomarse la molestia de crear pruebas automatizadas no va a hacer que funcione mejor. Si crear la
aplicación encuestas es el último fragmento de programa de Django que hará, entonces es verdad, usted no necesita saber cómo crear pruebas automatizadas. Sin embargo, si ese no
es el caso, ahora es un momento excelente para aprender.
Hasta cierto punto, “comprobar de que parece funcionar” será una prueba satisfactoria. En una aplicación más so sticada, es posible que tenga decenas de interacciones complejas
entre los componentes.
A change in any of those components could have unexpected consequences on the application’s behavior. Checking that it still “seems to work” could mean running through your code’s
functionality with twenty different variations of your test data to make sure you haven’t broken something - not a good use of your time.
Eso es especialmente cierto cuando las pruebas automatizadas pueden hacer esto por usted en cuestión de segundos. Si algo salió mal, las pruebas también ayudarán a identi car el
código que está causando el comportamiento inesperado.
A veces puede parecer un fastidio apartarse de su trabajo creativo y productivo de programación para afrontar la obligación poca atractiva y aburrida de escribir pruebas, particularmente
cuando sabe que su código funciona de forma adecuada.
Sin embargo, la tarea de escribir pruebas es mucho más grati cante que pasar horas probando su aplicación de forma manual o intentando identi car la causa de un problema recién
introducido.
Es un error pensar en las pruebas sólo como un aspecto negativo del desarrollo.
Sin las pruebas, el propósito o el comportamiento previsto de una aplicación podría ser bastante incomprensible. Aún cuando es su propio código, usted a veces se encontrará buscando
en él tratando de averiguar qué es exactamente lo que hace.
Las pruebas cambian eso, ellas iluminan su código desde adentro, y cuando algo sale mal, ellas se centran en la parte que salió mal; incluso si usted no se ha dado cuenta de que salió
mal.
You might have created a brilliant piece of software, but you will nd that many other developers will refuse to look at it because it lacks tests; without tests, they won’t trust it. Jacob
Kaplan-Moss, one of Django’s original developers, says «Code without tests is broken by design.»
Que otros desarrolladores quieran ver pruebas en su software antes de que se lo tomen en serio es una razón más para que usted comience a escribir las pruebas.
Some programmers follow a discipline called «test-driven development»; they actually write their tests before they write their code. This might seem counter-intuitive, but in fact it’s
similar to what most people will often do anyway: they describe a problem, then create some code to solve it. Test-driven development formalizes the problem in a Python test case.
La mayoría de las veces, un principiante en pruebas va a crear código y luego decidirá que este debe tener algunas pruebas. Tal vez hubiera sido mejor escribir algunas pruebas antes,
pero nunca es demasiado tarde para empezar.
A veces es difícil saber por dónde empezar con la escritura de pruebas. Si usted ha escrito varias miles de líneas de Python, elegir algo para probar podría no ser fácil. En tal caso, es
provechoso escribir su primera prueba la próxima vez que realice una modi cación, ya sea cuando agregue una nueva funcionalidad o solucione un error.
Con rm the bug by using the shell to check the method on a question whose date lies in the future:
/
Puesto que las cosas en el futuro no son “recientes”, esto es claramente erróneo.
Un lugar convencional para las pruebas de una aplicación se encuentra en el archivo tests.py de la aplicación; el sistema de pruebas encontrará automáticamente las pruebas en
cualquier archivo cuyo nombre comience con test.
polls/tests.py
import datetime
class QuestionModelTests(TestCase):
def test_was_published_recently_with_future_question(self):
"""
was_published_recently() returns False for questions whose pub_date
is in the future.
"""
time = timezone.now() + datetime.timedelta(days=30)
future_question = Question(pub_date=time)
self.assertIs(future_question.was_published_recently(), False)
Here we have created a django.test.TestCase subclass with a method that creates a Question instance with a pub_date in the future. We then check the output of
was_published_recently() - which ought to be False.
/
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)
Destroying test database for alias 'default'...
Different error?
If instead you’re getting a NameError here, you may have missed a step in Part 2 where we added imports of datetime and timezone to polls/models.py.
Copy the imports from that section, and try running your tests again.
en test_was_published_recently_with_future_question creó una instancia Question cuyo campo de pub_date está 30 días en el futuro
… y utilizando el método assertIs() descubrió que was_published_recently() retorna True, aunque queríamos que retornara False
La prueba nos informa que prueba falló e incluso la línea en la que se produjo el error.
Solucionando el bug
Ya sabemos cuál es el problema: Question.was_published_recently() debe devolver False si su pub_date está en el futuro. Modi que el método models.py, de modo que
este sólo retornará True si la fecha está también en el pasado:
polls/models.py
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
OK
Destroying test database for alias 'default'...
Después de identi car un bug, escribimos una prueba que lo expone y corregimos el bug en el código para que nuestra prueba pase.
Many other things might go wrong with our application in the future, but we can be sure that we won’t inadvertently reintroduce this bug, because running the test will warn us
immediately. We can consider this little portion of the application pinned down safely forever.
Agregue dos métodos de pruebas más a la misma clase, para probar el comportamiento del método de forma más completa:
polls/tests.py
def test_was_published_recently_with_old_question(self):
"""
was_published_recently() returns False for questions whose pub_date
is older than 1 day.
"""
time = timezone.now() - datetime.timedelta(days=1, seconds=1)
old_question = Question(pub_date=time)
self.assertIs(old_question.was_published_recently(), False)
def test_was_published_recently_with_recent_question(self):
"""
was_published_recently() returns True for questions whose pub_date
is within the last day.
"""
time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59)
recent_question = Question(pub_date=time)
self.assertIs(recent_question.was_published_recently(), True)
Y ahora tenemos tres pruebas que con rman que Question.was_published_recently() retorna valores razonables para preguntas pasadas, recientes y futuras.
Again, polls is a minimal application, but however complex it grows in the future and whatever other code it interacts with, we now have some guarantee that the method we have
written tests for will behave in expected ways.
En nuestra primera prueba, nos centramos detalladamente en el comportamiento interno del código. Para esta prueba, queremos comprobar su comportamiento como lo experimentaría
un usuario a través de un navegador web.
Antes de tratar de corregir algo, echemos un vistazo a las herramientas a nuestra disposición.
We will start again with the shell, where we need to do a couple of things that won’t be necessary in tests.py. The rst is to set up the test environment in the shell:
/
setup_test_environment() instala un procesador de plantillas que nos permite examinar algunos atributos adicionales sobre respuestas como response.context que de otra
forma no estarían disponibles. Tenga en cuenta que este método no crea una base de datos de pruebas, por lo que lo siguiente se ejecutará contra la base de datos existente y la salida
puede variar levemente dependiendo de cuáles preguntas usted ya creó. Puede obtener resultados inesperados si su TIME_ZONE en el archivo settings.py no es correcto. Si no
recuerda haberlo con gurado anteriormente, verifíquelo antes de continuar.
A continuación tenemos que importar la clase de cliente de prueba (más tarde en tests.py usaremos la clase django.test.TestCase que viene con su propio cliente, por lo que
esto no será necesario):
Con eso listo, podemos pedirle al cliente que haga un trabajo para nosotros:
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
"""Return the last five published questions."""
return Question.objects.order_by('-pub_date')[:5]
Tenemos que modi car el método get_queryset() y cambiarlo para que también compruebe la fecha comparándolo con timezone.now(). En primer lugar tenemos que añadir un
import:
polls/views.py
polls/views.py
def get_queryset(self):
"""
Return the last five published questions (not including those set to be
published in the future).
"""
return Question.objects.filter(
pub_date__lte=timezone.now()
).order_by('-pub_date')[:5]
Question.objects.filter(pub_date__lte=timezone.now()) retorna un queryset que contiene Questions cuya pub_date es menor o igual a, es decir, anterior o igual a
timezone.now.
polls/tests.py
y vamos a crear una función de atajo para crear preguntas, así como una nueva clase de pruebas:
polls/tests.py
def create_question(question_text, days):
"""
Create a question with the given `question_text` and published the
given number of `days` offset to now (negative for questions published
in the past, positive for questions that have yet to be published).
"""
time = timezone.now() + datetime.timedelta(days=days)
return Question.objects.create(question_text=question_text, pub_date=time)
class QuestionIndexViewTests(TestCase):
def test_no_questions(self):
"""
If no questions exist, an appropriate message is displayed.
"""
response = self.client.get(reverse('polls:index'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "No polls are available.")
self.assertQuerysetEqual(response.context['latest_question_list'], [])
def test_past_question(self):
"""
Questions with a pub_date in the past are displayed on the
index page.
"""
create_question(question_text="Past question.", days=-30)
response = self.client.get(reverse('polls:index'))
self.assertQuerysetEqual(
response.context['latest_question_list'],
['<Question: Past question.>']
)
def test_future_question(self):
"""
Questions with a pub_date in the future aren't displayed on
the index page.
"""
create_question(question_text="Future question.", days=30)
response = self.client.get(reverse('polls:index'))
self.assertContains(response, "No polls are available.")
self.assertQuerysetEqual(response.context['latest_question_list'], [])
def test_future_question_and_past_question(self):
"""
Even if both past and future questions exist, only past questions
are displayed.
"""
create_question(question_text="Past question.", days=-30)
create_question(question_text="Future question.", days=30)
response = self.client.get(reverse('polls:index'))
self.assertQuerysetEqual(
response.context['latest_question_list'],
['<Question: Past question.>']
)
def test_two_past_questions(self):
"""
The questions index page may display multiple questions.
"""
create_question(question_text="Past question 1.", days=-30)
create_question(question_text="Past question 2.", days=-5)
response = self.client.get(reverse('polls:index'))
self.assertQuerysetEqual(
response.context['latest_question_list'],
['<Question: Past question 2.>', '<Question: Past question 1.>']
)
En primer lugar es una función de atajo a las preguntas, create_question, para eliminar parte de la repetición del proceso de creación de preguntas.
test_no_questions no crea ninguna pregunta, pero comprueba el mensaje: «No hay encuestas disponibles.» y veri ca que latest_question_list esté vacía. Tenga en cuenta
que la clase django.test.TestCase ofrece algunos métodos de aserción adicionales. En estos ejemplos utilizamos :meth:~django.test.SimpleTestCase.assertContains()` y
assertQuerysetEqual().
En test_future_question creamos una pregunta con una pub_date en el futuro. La base de datos se reinicia para cada método de prueba, por lo que la primera pregunta ya no está
allí, de modo que de nuevo el índice no debería tener ninguna pregunta.
Y así sucesivamente. En efecto, estamos utilizando las pruebas para contar una historia del ingreso de datos en el sitio administrativo y experiencia de usuario en el sitio, y comprobar
que los resultados esperados se publican en cada estado y para cada nuevo cambio en el estado del sistema.
Probando la DetailView
Lo que tenemos funciona bien; sin embargo, a pesar de que las preguntas futuras no aparecen en el índice, los usuarios pueden todavía llegar a ellas si saben o adivinan la dirección URL
correcta. Así que tenemos que agregar una restricción similar a la DetailView:
polls/views.py
class DetailView(generic.DetailView):
...
def get_queryset(self):
"""
Excludes any questions that aren't published yet.
"""
return Question.objects.filter(pub_date__lte=timezone.now())
We should then add some tests, to check that a Question whose pub_date is in the past can be displayed, and that one with a pub_date in the future is not:
polls/tests.py
class QuestionDetailViewTests(TestCase):
def test_future_question(self):
"""
The detail view of a question with a pub_date in the future
returns a 404 not found.
"""
future_question = create_question(question_text='Future question.', days=5)
url = reverse('polls:detail', args=(future_question.id,))
response = self.client.get(url)
self.assertEqual(response.status_code, 404)
def test_past_question(self):
"""
The detail view of a question with a pub_date in the past
displays the question's text.
"""
past_question = create_question(question_text='Past Question.', days=-5)
url = reverse('polls:detail', args=(past_question.id,))
response = self.client.get(url)
self.assertContains(response, past_question.question_text)
También podríamos mejorar nuestra aplicación de otras maneras, agregando pruebas a lo largo del camino. Por ejemplo, es una tontería que se puedan publicar Questions en el sitio
que no tienen Choices. Por lo tanto, nuestras vistas podrían comprobar esto y excluir dichas Questions. Nuestras pruebas crearían una Question sin Choices y luego probarían que
no está publicada, así como crearían una Question similar con Choices y probarían que está publicada.
Quizás se les debería permitir a los usuarios registrados en el sitio administrativo ver las Questions que no han sido publicadas, pero no a los visitantes ordinarios. Una vez más: lo que
se tenga que agregar al software para lograr esto debería ir acompañado de una prueba, ya sea que escriba la prueba primero y luego haga que el código pase la prueba, o primero
solucione la lógica en el código y luego escriba una prueba para probarlo.
En un momento dado usted está obligado a examinar sus pruebas y a preguntarse si su código sufre de exceso de pruebas, lo que nos lleva a:
No importa, deje que crezcan. Por lo general, usted puede escribir una prueba una vez y luego olvidarse de ella. Esta seguirá cumpliendo su función útil mientras usted continúe
desarrollando su programa.
A veces las pruebas tendrán que ser actualizadas. Supongamos que modi camos nuestras vistas de modo que sólo las Questions con Choices se publiquen. En ese caso, muchas de
nuestras pruebas existentes fallarán, indicándonos exactamente qué pruebas necesitan ser modi cadas para actualizarlas, de modo que hasta ese punto las pruebas ayudan a ocuparse
de sí mismas.
En el peor de los casos, a medida que continúe desarrollando, usted podría encontrar que tiene algunas pruebas que ahora son redundantes. Incluso eso no es un problema, cuando se
trata de pruebas, la redundancia es algo bueno.
Siempre y cuando las pruebas se organicen de forma razonable, no van a ser difíciles de manejar. Las reglas básicas de uso incluyen el hecho de tener:
un método de prueba independiente para cada conjunto de condiciones que usted quiere probar
Pruebas adicionales
Este tutorial sólo presenta algunos de los temas fundamentales de las pruebas. Hay mucho más que usted puede hacer y una serie de herramientas muy útiles a su disposición para
lograr algunas cosas muy interesantes.
Por ejemplo, aunque nuestras pruebas han tratado aquí algo de la lógica interna de un modelo y la forma en que nuestras vistas publican información, usted puede utilizar un framework
«en el navegador» como Selenium para probar la forma en que su HTML en realidad se renderiza en un navegador. Estas herramientas le permiten comprobar no sólo el comportamiento
de su código Django, sino también, por ejemplo, el de su JavaScript. ¡Es impresionante ver cómo las pruebas ejecutan un navegador y comienzan a interactuar con su sitio como si
estuviese siendo operado por un humano! Django incluye LiveServerTestCase para facilitar la integración con herramientas como Selenium.
Si usted tiene una aplicación compleja, es posible que desee ejecutar las pruebas de forma automática con cada commit a efectos de la integración continua_, por lo que el control de
calidad está en sí, al menos parcialmente, automatizado.
Una buena manera de detectar las partes de su aplicación que no han sido probadas es comprobar la cobertura de código. Esto también ayuda a identi car el código frágil o incluso
muerto. Si no puede probar un trozo de código, por lo general signi ca que el código debe ser reestructurado o eliminado. La cobertura ayudará a identi car el código muerto. Consulte
Integration with coverage.py para más detalles.
¿Qué sigue?
Para más detalles sobre las pruebas, consulte Las pruebas en Django.
Cuando esté familiarizado con las pruebas de las vistas de Django, lea la parte 6 de este tutorial para aprender sobre la gestión de los archivos estáticos.
Escribiendo su primera aplicación en Django, parte 6
Este tutorial comienza donde quedó el Tutorial 5. Hemos creado una aplicación Web encuestas probada y ahora vamos a agregar una hoja de estilo y una imagen.
Aparte del HTML generado por el servidor, las aplicaciones Web por lo general tienen que servir archivos adicionales tales como imágenes, JavaScript o CSS necesarios para renderizar
la página web completa. En Django, nos referimos a estos archivos como «archivos estáticos».
For small projects, this isn’t a big deal, because you can keep the static les somewhere your web server can nd it. However, in bigger projects – especially those comprised of multiple
apps – dealing with the multiple sets of static les provided by each application starts to get tricky.
Eso es para lo que django.contrib.staticfiles es: recolecta los archivos estáticos de cada una de sus aplicaciones (y de cualquier otro lugar que usted especi que) en un solo
lugar que se puede servir fácilmente en la producción.
If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.
La opción STATICFILES_FINDERS de Django contiene una lista de buscadores que saben cómo hallar archivos estáticos de diversas fuentes. Uno de los predeterminados es
AppDirectoriesFinder que busca un subdirectorio «static» en cada una de las INSTALLED_APPS, como el que está en polls que acabamos de crear. El sitio administrativo utiliza
la misma estructura de directorios para sus archivos estáticos.
Within the static directory you have just created, create another directory called polls and within that create a le called style.css. In other words, your stylesheet should be at
polls/static/polls/style.css. Because of how the AppDirectoriesFinder static le nder works, you can refer to this static le in Django as polls/style.css, similar to
how you reference the path for templates.
Just like templates, we might be able to get away with putting our static les directly in polls/static (rather than creating another polls subdirectory), but it
would actually be a bad idea. Django will choose the rst static le it nds whose name matches, and if you had a static le with the same name in a different
application, Django would be unable to distinguish between them. We need to be able to point Django at the right one, and the best way to ensure this is by
namespacing them. That is, by putting those static les inside another directory named for the application itself.
polls/static/polls/style.css
li a {
color: green;
}
polls/templates/polls/index.html
{% load static %}
/
Reload http://localhost:8000/polls/ and you should see that the question links are green (Django style!) which means that your stylesheet was properly loaded.
Agregando una imagen de fondo
A continuación, vamos a crear un subdirectorio para imágenes. Cree un subdirectorio images en el directorio polls/static/polls/. Dentro de este directorio, ponga una imagen
llamada background.gif. En otras palabras, ponga su imagen en polls/static/polls/images/background.gif.
polls/static/polls/style.css
body {
background: white url("images/background.gif") no-repeat;
}
Reload http://localhost:8000/polls/ and you should see the background loaded in the top left of the screen.
Advertencia
The {% static %} template tag is not available for use in static les which aren’t generated by Django, like your stylesheet. You should always use relative paths
to link your static les between each other, because then you can change STATIC_URL (used by the static template tag to generate its URLs) without having to
modify a bunch of paths in your static les as well.
Estos son los fundamentos. Para más detalles sobre la con guración y otra información que se incluye con el framework consulte la guía paso-a-paso de los archivos estáticos y la
referencia de los archivos estáticos. Implementación de archivos estáticos habla sobre cómo utilizar los archivos estáticos en un servidor real.
Cuando esté familiarizado con los archivos estáticos, lea la parte 7 de este tutorial para aprender a personalizar el sitio administrativo generado automáticamente de Django.
Escribiendo su primera aplicación Django, parte 7
Este tutorial comienza donde quedó el Tutorial 6. Continúamos con la aplicación Web encuestas y nos vamos a enfocar en personalizar el sitio administrativo de Django generado
automáticamente que estudiamos primero en el Tutorial 2.
If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.
Veamos cómo funciona esto reordenando los campos en el formulario de edición. Reemplace la línea admin.site.register(Question) con:
polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
fields = ['pub_date', 'question_text']
admin.site.register(Question, QuestionAdmin)
Usted seguirá este patrón - cree una clase de modelo del sitio administrativo y luego pásela como el segundo argumento a admin.site.register() - cada vez que necesite cambiar
las opciones del sitio administrativo para un modelo.
Esta modi cación concreta citada anteriormente hace que la «Publication date» se anteponga al campo «Question»:
Esto no es tan impresionante con sólo dos campos, pero para los formularios del sitio administrativo con docenas de campos, elegir un orden intuitivo es un detalle importante de
usabilidad.
Y hablando de formularios con docenas de campos, es posible que desee dividir el formulario en grupos de campos:
polls/admin.py
from django.contrib import admin
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date']}),
]
admin.site.register(Question, QuestionAdmin)
El primer elemento de cada tupla en fieldsets es el título del grupo de campos. Así es como se ve el formulario ahora:
Sin embargo.
There are two ways to solve this problem. The rst is to register Choice with the admin just as we did with Question:
polls/admin.py
Ahora «Choices» es una opción disponible en el sitio administrativo de Django. El formulario «Add choice» se ve así:
En ese formulario, el campo «Question» es un cuadro de selección que contiene cada pregunta de la base de datos. Django sabe que una ForeignKey debería estar representada en el
sitio administrativo como un cuadro <select>. En nuestro caso, solo existe una pregunta en este momento.
También tenga en cuenta el enlace «Add another» que está al lado de «Question». Cada objeto que tiene una relación ForeignKey con otro obtiene este libremente . Al hacer clic en
«Add another», aparecerá una ventana emergente con el formulario «Add question». Si usted agrega una pregunta en esa ventana y hace clic en «Save», Django guardará la pregunta en la
base de datos y la agregará dinámicamente como la opción seleccionada en el formulario «Add choice» que usted está mirando.
Pero, en realidad, se trata de una forma ine ciente de añadir objetos Choice al sistema. Sería mejor si usted pudiese agregar muchas Choices directamente cuando crea el objeto
Question. Hagámoslo realidad.
Elimine la llamada register() para el modelo Choice. Después, edite el código de registro de Question para que diga:
polls/admin.py
class ChoiceInline(admin.StackedInline):
model = Choice
extra = 3
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['question_text']}),
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
]
inlines = [ChoiceInline]
admin.site.register(Question, QuestionAdmin)
Esto le indica a Django: «Los objetos Choice se editan en la página de administración Question. De forma predeterminada, proporciona su cientes campos para 3 opciones.»
Al nal de los tres espacios actuales se encuentra un enlace «Add another choice». Si hace clic en él, se añadirá un espacio nuevo. Si desea eliminar el espacio adicional, usted puede
hacer clic en la X en la parte superior derecha del espacio añadido. Tenga en cuenta que no puede eliminar los tres espacios originales. Esta imagen muestra un espacio añadido:
One small problem, though. It takes a lot of screen space to display all the elds for entering related Choice objects. For that reason, Django offers a tabular way of displaying inline
related objects. To use it, change the ChoiceInline declaration to read:
polls/admin.py
class ChoiceInline(admin.TabularInline):
#...
Los objetos relacionados se muestran en un formato más compacto basado en tablas con esa TabularInline (en lugar de StackedInline):
Tenga en cuenta que hay una columna «Delete?» extra que permite la eliminación de las añadidas utilizando el botón «Add Another Choice» y las las que ya han sido guardadas.
polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ('question_text', 'pub_date')
For good measure, let’s also include the was_published_recently() method from Tutorial 2:
polls/admin.py
class QuestionAdmin(admin.ModelAdmin):
# ...
list_display = ('question_text', 'pub_date', 'was_published_recently')
Usted puede hacer clic en las cabeceras de las columnas para ordenar por esos valores ,excepto en el caso de la cabecera was_published_recently, porque ordenar por la salida de
un método arbitrario no está soportado. También tenga en cuenta que la cabecera de la columna was_published_recently es, por defecto, el nombre del método (con guiones bajos
reemplazado con espacios), y que cada línea contiene la representación de cadena de la salida.
Usted puede mejorar eso al darle a ese método (en el archivo polls/models.py) algunos atributos, de la siguiente manera:
polls/models.py
class Question(models.Model):
# ...
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
was_published_recently.admin_order_field = 'pub_date'
was_published_recently.boolean = True
was_published_recently.short_description = 'Published recently?'
Para obtener más información sobre estas propiedades del método, consulte list_display.
Edite de nuevo su archivo polls/admin.py y añada una mejora a la página Question en la lista de cambios: ltre utilizando el list_filter. Agregue la siguiente línea a
QuestionAdmin:
list_filter = ['pub_date']
Eso añade una barra lateral «Filter» que le permite a los usuarios ltrar la lista de cambios mediante el campo pub_date:
El tipo de ltro que se muestra depende del tipo de campo que está ltrando. Debido a que la pub_date es una DateTimeField, Django sabe dar opciones de ltro apropiadas: «Any
date», «Today», «Past 7 days», «This month», «This year».
search_fields = ['question_text']
Eso añade un cuadro de búsqueda en la parte superior de la lista de cambios. Cuando alguien introduce los términos de búsqueda, Django buscará el campo question_text. Usted
puede utilizar tantos campos como desee, sin embargo, ya que utiliza una petición LIKE detrás de bastidores, limitar el número de campos de búsqueda a un número razonable le
facilitará la búsqueda a su base de datos.
Ahora también es un buen momento para señalar que las listas de cambios le dan paginación libre. El modo predeterminado muestra 100 items por página. Paginación de la
lista de cambios, cuadros de búsqueda, :attr:`filtros, jerarquías de fecha y orden de la cabecera de columnas todos trabajan juntos como usted piensa
que deberían.
You can change it, though, using Django’s template system. The Django admin is powered by Django itself, and its interfaces use Django’s own template system.
Abra el archivo de con guraciones (mysite/settings.py, recuerde) y añada una opción DIRS en la opción TEMPLATES:
mysite/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
DIRS es una lista de directorios del sistema de archivos utilizada para comprobar cuando se cargan las plantillas de Django; es una ruta de búsqueda.
Al igual que los archivos estáticos podríamos tener todas nuestras plantillas juntas en un gran directorio de plantillas y funcionaría perfectamente. Sin embargo,
las plantillas que pertenecen a una determinada aplicación deberían ser puestas en el directorio de plantillas de la aplicación (por ejemplo, polls/templates)
en lugar del directorio (templates) del proyecto. Hablaremos con más detalle por qué hacemos esto en el tutorial de aplicaciones reutilizables.
Ahora cree un directorio llamado admin dentro de templates y copie la plantilla admin/base_site.html desde dentro del directorio de plantillas predeterminado del sitio
administrativo de Django en el código fuente de Django (django/contrib/admin/templates) en ese directorio.
Si tiene di cultad para encontrar donde están localizados los archivos fuente de Django en su sistema, ejecute el siguiente comando:
/
Then, edit the le and replace {{ site_header|default:_('Django administration') }} (including the curly braces) with your own site’s name as you see t. You should end
up with a section of code like:
{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}
Utilizamos este método para enseñarle cómo reemplazar las plantillas. En un proyecto real, usted probablemente utilizaría el atributo
django.contrib.admin.AdminSite.site_header para hacer este ajuste particular con mayor facilidad.
Este archivo de plantillas contiene una gran cantidad de texto como {% block branding%} y {{title}}. Las etiquetas {% y {{ son parte del lenguaje de plantillas de Django.
Cuando Django crea admin/base_site.html, este lenguaje de plantilla será evaluado para generar la página HTML de nitiva, como vimos en el Tutorial 3.
Note that any of Django’s default admin templates can be overridden. To override a template, do the same thing you did with base_site.html – copy it from the default directory into
your custom directory, and make changes.
Nuestra aplicación encuestas no es muy compleja y no necesita las plantillas personalizadas del sitio administrativo. Pero si se hiciera más so sticada y requiriera la modi cación de las
plantillas convencionales del sitio administrativo de Django para algunas de sus funciones, sería más sensato modi car las plantillas de la aplicación, en lugar de las que están en el
proyecto. De esa manera, usted podría incluir la aplicación encuestas en cualquier nuevo proyecto y estaría seguro de que esta encontraría las plantillas personalizadas que necesitaba.
Consulte la documentación sobre la carga de plantillas para obtener más información sobre cómo Django encuentra sus plantillas.
Personalice la página del índice del sitio administrativo
En este sentido, es posible que desee personalizar la apariencia de la página de índice del sitio administrativo de Django.
Por defecto, muestra todas las aplicaciones que se encuentran en INSTALLED_APPS que han sido registradas en la aplicación del sitio administrativo en orden alfabético. Es posible que
desee realizar cambios signi cativos en el diseño. Después de todo, el índice es probablemente la página más importante del sitio administrativo y debería ser fácil de usar.
La plantilla a personalizar es admin/index.html. (Haga lo mismo que hizo con admin/base_site.html en la sección anterior: cópiela desde el directorio predeterminado en el
directorio de plantillas personalizadas). Edite el archivo y verá que utiliza una variable de plantilla llamada app_list. Esa variable contiene todas las aplicaciones instaladas de Django.
En lugar de utilizar esa, usted puede predeterminar enlaces a páginas del sitio administrativo especí cas de objeto de la manera que le parezca mejor.
¿Qué sigue?
El tutorial para principiantes naliza aquí. Mientras tanto, es posible que desee ver algunos consejos sobre a dónde ir a partir de ahora.
Si está familiarizado con el empaquetado Python e interesado en aprender cómo convertir la aplicación encuestas en una «aplicación reutilizable», consulte el tutorial avanzado: Cómo
escribir aplicaciones reutilizables.
Tutorial Avanzado: Cómo escribir aplicaciones reutilizables
Este tutorial avanzado comienza donde quedó el : doc:Tutorial 7 </intro/tutorial07>. Vamos a convertir nuestra encuesta Web en un paquete independiente Python que puedes reutilizar
en nuevos proyectos y compartir con otras personas.
Si recientemente no has completado Tutoriales 1-7, nosotros te recomendamos que los revises para que tu proyecto de ejemplo coincida con el que se describe abajo.
La reusabilidad importa ¶
Requiere mucho trabajo diseñar, crear, probar y mantener una aplicación web. Muchos proyectos de Python y Django comparten problemas comunes. ¿No sería genial si pudiéramos
ahorrarnos algo de este trabajo repetido?
Reusability is the way of life in Python. The Python Package Index (PyPI) has a vast range of packages you can use in your own Python programs. Check out Django Packages for existing
reusable apps you could incorporate in your project. Django itself is also a normal Python package. This means that you can take existing Python packages or Django apps and compose
them into your own web project. You only need to write the parts that make your project unique.
Let’s say you were starting a new project that needed a polls app like the one we’ve been working on. How do you make this app reusable? Luckily, you’re well on the way already. In
Tutorial 1, we saw how we could decouple polls from the project-level URLconf using an include. In this tutorial, we’ll take further steps to make the app easy to use in new projects and
ready to publish for others to install and use.
¿Paquete? ¿Aplicación?
Un paquete de Python proporciona una forma de agrupar código Python relacionado para reutilizarlo de forma fácil. Un paquete contiene uno o más archivos de
código Python (también conocidos como «módulos»).
Un paquete puede ser importado con import foo.bar o from foo import bar. Para que un directorio (como polls) cree un paquete, debe contener un
archivo especial __init__.py, incluso si este archivo está vacío.
A Django application is a Python package that is speci cally intended for use in a Django project. An application may use common Django conventions, such as
having models, tests, urls, and views submodules.
Posteriormente, usamos el término empaquetamiento para describir el proceso de hacer que un paquete Python sea fácil de instalar para los demás. Sabemos
que puede ser un poco confuso.
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
0001_initial.py
models.py
static/
polls/
images/
background.gif
style.css
templates/
polls/
detail.html
index.html
results.html
tests.py
urls.py
views.py
templates/
admin/
base_site.html
Ha creado mysite/templates en Tutorial 7, y polls/templates en Tutorial 3. Ahora quizá queda más claro por qué se separan los directorios de plantillas en el proyecto y la
aplicación: todo lo que forma parte de la applicación de encuestas está en polls. Esto hace que la aplicación esté auto-contenida y sea más sencillo incluirla en un nuevo proyecto.
El directorio polls ahora se podría copiar en un nuevo proyecto de Django e inmediatamente ser reutilizado. Sin embargo, no está listo para ser publicado. Para ello, necesitamos
empaquetar la aplicación para hacer más fácil que otros la instalen.
Empaquetando su aplicación
El empaquetamiento en Python se re ere a la preparación de su aplicación en un formato especí co que pueda ser fácilmente instalado y utilizado. Django mismo está empaquetado de
forma muy similar a esta. Para una aplicación pequeña como polls este proceso no es muy complejo.
1. En primer lugar, cree un directorio principal para polls fuera de su proyecto Django. Nombre este directorio como django-polls.
Al momento de elegir un nombre para su paquete, revise recursos como PyPI para evitar con ictos de nombres con los paquetes existentes. Con
frecuencia es útil anteponer django- a su nombre de módulo cuando crea un paquete para distribuir. Esto ayuda a otros que estén buscando
aplicaciones Django identi car su aplicación como particular de Django.
Las etiquetas de la aplicación (es decir, la parte nal del camino punteado a los paquetes de las aplicaciones) deben ser únicas en INSTALLED_APPS.
Evite utilizar la misma etiqueta como las de cualquier paquete contrib de Django:, por ejemplo, auth, admin, o messages.
django-polls/README.rst
=====
Polls
=====
Quick start
-----------
INSTALLED_APPS = [
...
'polls',
]
path('polls/', include('polls.urls')),
4. Cree un archivo django-polls/LICENSE. Elegir una licencia está fuera del alcance de este tutorial, pero basta con señalar que el código liberado públicamente sin ninguna
licencia es inútil. Django y muchas aplicaciones compatibles con Django se distribuyen bajo la licencia BSD, sin embargo, usted es libre de elegir su propia licencia. Sólo tenga
en cuenta que la elección de su licencia repercutirá sobre quién podrá utilizar su código.
5. Next we’ll create setup.cfg and setup.py les which detail how to build and install the app. A full explanation of these les is beyond the scope of this tutorial, but the
setuptools documentation has a good explanation. Create the les django-polls/setup.cfg and django-polls/setup.py with the following contents:
django-polls/setup.cfg
[metadata]
name = django-polls
version = 0.1
description = A Django app to conduct Web-based polls.
long_description = file: README.rst
url = https://www.example.com/
author = Your Name
author_email = [email protected]
license = BSD-3-Clause # Example license
classifiers =
Environment :: Web Environment
Framework :: Django
Framework :: Django :: X.Y # Replace "X.Y" as appropriate
Intended Audience :: Developers
License :: OSI Approved :: BSD License
Operating System :: OS Independent
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Topic :: Internet :: WWW/HTTP
Topic :: Internet :: WWW/HTTP :: Dynamic Content
[options]
include_package_data = true
packages = find:
django-polls/setup.py
setup()
6. Solo se incluyen módulos y paquetes de Python en el paquete de forma predeterminada. Para incluir archivos adicionales, tendremos que crear un archivo MANIFEST.in. La
documentación setuptools referidos en el paso anterior abordan este archivo de forma detallada. Para incluir las plantillas, el README.rst y nuestro archivo LICENSE, cree un
archivo django-polls/MANIFEST.in con el siguiente contenido:
django-polls/MANIFEST.in
include LICENSE
include README.rst
recursive-include polls/static *
recursive-include polls/templates *
7. Es opcional pero recomendado incluir documentación detallada con su aplicación. Cree un directorio django-polls/docs vacío para la documentación futura . Agregue una
línea adicional al archivo django-polls/MANIFEST.in:
recursive-include docs *
Tenga en cuenta que el directorio docs no se incluirá en su paquete a menos que usted agregue algunos archivos a este. Muchas aplicaciones Django proporcionan también
su documentación online a través de sitios como readthedocs.org.
8. Intente generar su paquete con python setup.py sdist (ejecute desde dentro de django-polls). Esto crea un directorio llamado dist y crea su nuevo paquete,
django-polls-0.1.tar.gz.
For more information on packaging, see Python’s Tutorial on Packaging and Distributing Projects.
Los siguientes pasos instalan django-polls como una librería de usuario. La instalación a nivel de usuario tiene muchas ventajas con respecto a instalar el
paquete a nivel de sistema, como poder ser usado en sistemas donde no se tiene acceso de administrador así como impedir que el paquete afecte servicios del
sistema y a otros usuarios del ordenador.
Note that per-user installations can still affect the behavior of system tools that run as that user, so using a virtual environment is a more robust solution (see
below).
2. Con suerte, su proyecto Django ahora debería funcionar de nuevo correctamente. Ejecute el servidor de nuevo para con rmar esto.
Publicando su aplicación
Ahora que hemos empaquetado y probado django-polls, está lista para compartir con el mundo! Si esto no era más que un ejemplo, usted ahora podría:
Post the package on a public repository, such as the Python Package Index (PyPI). packaging.python.org has a good tutorial for doing this.
Modi car las librerías de usuario puede afectar a otro programa Python en su sistema.
Usted no podrá ejecutar distintas versiones de este paquete (u otros con el mismo nombre).
Typically, these situations only arise once you’re maintaining several Django projects. When they do, the best solution is to use venv. This tool allows you to maintain multiple isolated
Python environments, each with its own copy of the libraries and package namespace.
Qué leer después
De modo que usted ha leído todo el material introductorio y ha decidido que le gustaría seguir usando Django. Sólo hemos arañado la super cie con esta introducción (de hecho, si usted
ha leído cada palabra, usted ha leído un 5% de la totalidad de la documentación).
Bueno, siempre hemos sido grandes fans de aprender haciendo. En este punto, usted debe saber lo su ciente como para iniciar un proyecto por su cuenta y empezar a divertirse.
Conforme necesite aprender nuevos trucos, vuelva a la documentación.
We’ve put a lot of effort into making Django’s documentation useful, clear and as complete as possible. The rest of this document explains more about how the documentation works so
that you can get the most out of it.
(Sí, se trata de documentación sobre la documentación. Tenga la seguridad de que no tenemos planes de escribir un documento de cómo leer el documento sobre la documentación.)
Buscando documentación
Django’s got a lot of documentation – almost 450,000 words and counting – so nding what you need can sometimes be tricky. A good place to start is the Índice. We also recommend
using the builtin search feature.
El material introductorio está diseñado para los principiantes en Django – o en el desarrollo web en general. No trata nada en profundidad, sino que da una introducción de alto nivel
de cómo «se siente» desarrollar en Django.
Por otro lado, las guías temáticas profundizan en las secciones individuales de Django. Hay guías completas para el sistema de modelos de Django, motor de plantillas, framework
de formularios y mucho más.
Aquí es probablemente donde usted querrá pasar la mayor parte de su tiempo; si usted avanza en el estudio de estas guías debe salir sabiendo casi todo lo que hay que saber
acerca de Django.
El desarrollo web suele ser amplio, pero no profundo; los problemas abarcan muchos ámbitos. Hemos escrito un conjunto de guías paso a paso que responden las preguntas
comúnes tipo «¿Cómo puedo…?». Aquí encontrará información sobre cómo Crear PDFs con Django, escribir etiquetas de plantilla personalizadas y más.
Las guías y tutoriales paso a paso no abarcan cada clase, función y método disponible en Django, eso sería abrumador cuando usted está tratando de aprender. En su lugar, la
información sobre las clases, funciones, métodos y módulos individuales se guardan en la referencia. Aquí es donde buscará la información sobre una función en particular o lo que
usted necesite.
Si usted está interesado en la implementación de un proyecto para el uso público, nuestra documentación tienen varias guías para diversas con guraciones de implementación, así
como una lista de implementación para algunas cosas que usted tendrá que considerar.
Finally, there’s some «specialized» documentation not usually relevant to most developers. This includes the release notes and internals documentation for those who want to add
code to Django itself, and a few other things that don’t t elsewhere.
Para hacer correcciones de contenido tales como correcciones gramaticales y de errores tipográ cos.
Para añadir información y/o ejemplos a las secciones existentes que necesitan ser ampliadas.
Para documentar las funcionalidades de Django que aún no están documentadas. (La lista de dichas funcionalidades se reduce, sin embargo, existe a pesar de ello.)
Para agregar la documentación de las nuevas características a medida que estas se añaden o cuando cambian las APIs de Django o los comportamientos.
Django’s documentation is kept in the same source control system as its code. It lives in the docs directory of our Git repository. Each document online is a separate text le in the
repository.
Dónde conseguirla
Usted puede leer la documentación de Django de varias maneras. Las formas de leer la documentación están en orden de preferencia:
En la Web
The most recent version of the Django documentation lives at https://docs.djangoproject.com/en/dev/. These HTML pages are generated automatically from the text les in source
control. That means they re ect the «latest and greatest» in Django – they include the very latest corrections and additions, and they discuss the latest Django features, which may only
be available to users of the Django development version. (See Diferencias entre versiones below.)
Le animamos a ayudar a mejorar la documentación mediante la presentación de cambios, correcciones y sugerencias en el ticket system. Los desarrolladores de Django monitorean
activamente el sistema de tickets y utilizan sus comentarios y sugerencias para mejorar la documentación para todo el mundo.
Sin embargo, tenga en cuenta que las tickets deberían estar relacionadas expresamente con la documentación, en lugar de hacer preguntas generales de soporte técnico. Si usted
necesita ayuda con su con guración particular de Django, pruebe en su lugar la lista de correos de los django-users o en el canal de chat #django IRC.
If you’re using an o cial release of Django, the zipped package (tarball) of the code includes a docs/ directory, which contains all the documentation for that release.
If you’re using the development version of Django (aka the master branch), the docs/ directory contains all of the documentation. You can update your Git checkout to get the latest
changes.
Una forma de baja tecnología de aprovechar la documentación de textos es mediante el uso de la utilidad grep de Unix para buscar una expresión en toda la documentación. Por
ejemplo, esta le mostrará cada referencia de la expresión «max_length» en cualquier documento de Django:
/
La documentación de Django utiliza un sistema llamado Sphinx para convertir el texto plano en HTML. Usted tendrá que instalar Sphinx bien sea descargando e instalando el
paquete desde el sitio web de Sphinx o con pip:
/
Then, use the included Makefile to turn the documentation into HTML:
$ cd path/to/django/docs
$ make html
cd path\to\django\docs
make.bat html
The development documentation at https://docs.djangoproject.com/en/dev/ is from the master branch. These docs correspond to the latest feature release, plus whatever features
have been added/changed in the framework since then.
As we add features to Django’s development version, we update the documentation in the same Git commit transaction.
To distinguish feature changes/additions in the docs, we use the phrase: «New in Django Development version» for the version of Django that hasn’t been released yet, or «New in
version X.Y» for released versions.
Escribiendo su primer parche para Django
Introducción
¿Interesado en dar un poco a la comunidad? Quizás ha encontrado un bug en Django que le gustaría ver solucionado, o quizás hay una pequeña característica que quiera agregar.
Contributing back to Django itself is the best way to see your own concerns addressed. This may seem daunting at rst, but it’s a well-traveled path with documentation, tooling, and a
community to support you. We’ll walk you through the entire process, so you can learn by example.
Ver también
Si usted está buscando una referencia sobre cómo presentar parches, consulte la documentación Submitting patches.
Para este tutorial, esperamos que comprenda al menos el funcionamiento básico de Django. Esto signi ca que usted no tendría problemas estudiando los tutoriales existentes para crear
su primera aplicación Django. Adicionalmente, debería tener una buena comprensión de Python. Si no es así, Dive into Python es un libro fantástico (y gratuito) disponible en línea para
los programadores que comienzan en Python.
Aquellos de ustedes que no están familiarizados con los sistemas de control de versiones y Trac encontrarán que este tutorial y sus vínculos incluyen información su ciente para
empezar. Sin embargo, es probable que quiera leer un poco más acerca de estas diferentes herramientas si usted planea contribuir a Django con regularidad.
Sin embargo, en su mayor parte, este tutorial trata de explicar tanto como sea posible, de modo que pueda ser de utilidad para la audiencia más amplia.
Si presentas problemas leyendo este tutorial, por favor envíe un mensaje a django-developers o visita #django-dev en irc.freenode.net para chatear con otros
usuarios de Django que podrían ayudarte.
Instalando Git.
Probando su parche.
Una vez que haya terminado el tutorial, puede revisar el resto de la documentación para contribuir con Django. Contiene una gran cantidad de información de lectura obligatoria para todo
el que desee convertirse en colaborador habitual de Django. Si tiene preguntas, es probable que obtenga las respuestas.
¡Python 3 es requerido!
La versión actual de Django no soporta Python 2.7. Obtén Python 3 en la página de descargas de Python o con el gestor de paquetes de tu sistema operativo.
Instalando Git
Para este tutorial, necesitará instalar Git para descargar la versión actual de desarrollo de Django y generar archivos de revisión de los cambios que realice.
Para revisar si tiene o no instalado Git , ejecute git en la línea de comandos. Si recibe un mensaje diciendo que el comando no pudo ser encontrado, tendrá que descargarlo e instalarlo,
consulte la página de descarga de Git.
Si no estás familiarizado con Git, siempre se puede encontrar más información sobre sus comandos (una vez instalado) escribiendo git help en la línea de comandos.
/
Puedes añadir el argumento --depth 1 al comando git clone para evitar descargar todo el historial de commits de Django, el cual reduce la transferencia de
datos de ~250MB a ~70MB
Ahora que tiene una copia local de Django, puede instalarla como si fuera a instalar cualquier paquete utilizando pip. La forma más conveniente de hacerlo es mediante un entorno
virtual, que es una función incorporada en Python que le permite mantener un directorio separado de paquetes instalados para cada uno de sus proyectos para que no inter eran entre sí.
Es una buena idea mantener todos sus entornos virtuales en un solo lugar, por ejemplo, en `` virtualenvs /`` en su directorio de inicio.
/
$ source ~/.virtualenvs/djangodev/bin/activate
$ . ~/.virtualenvs/djangodev/bin/activate
You have to activate the virtual environment whenever you open a new terminal window.
El nombre del entorno virtual actualmente activado se muestra en la línea de comandos para ayudarlo a realizar un seguimiento de cuál está utilizando. Todo lo que instales a través de
pip mientras se muestre este nombre se instalará en ese entorno virtual, aislado de otros entornos y paquetes del systema.
/
The installed version of Django is now pointing at your local copy by installing in editable mode. You will immediately see any changes you make to it, which is of great help when writing
your rst patch.
Antes de ejecutar el conjunto de pruebas, instale sus dependencias, primero cambiándo al directorio tests/ de Django y después ejecutando:
/
Si encuentra un error durante la instalación, puede que su sistema carezca de alguna dependencia para uno o más de los paquetes de Python. Consulte la documentación del paquete
que falla o busque en la web el mensaje de error que encuentre.
Ahora estamos listos para ejecutar el conjunto de pruebas. Si estás utilizando GNU/Linux, macOS o alguna otra distribución de Unix, ejecuta:
/
$ ./runtests.py
Now sit back and relax. Django’s entire test suite has thousands of tests, and it takes at least a few minutes to run, depending on the speed of your computer.
Mientras se ejecuta la suite de pruebas de Django, verá una secuencia de caracteres que representan el estado de cada prueba a medida que se completa. `` E`` indica que un error se
planteó durante una prueba, y `` F`` indica las a rmaciones de una prueba fallida. Ambos de estos son considerados como fallas de prueba. Mientras tanto, `` x`` y `` s`` indicaron fallas
esperadas y pruebas omitidas, respectivamente. Los puntos indican pruebas superadas.
Las pruebas omitidas se deben usualmente a la ausencia de bibliotecas externas requeridas para la ejecución de los test; ver Running all the tests para la lista de dependencias y estar
seguro de instalar aquellas relacionadas con los cambios que estás haciendo (no necesitamos ninguna para esta tutorial). Algunas pruebas son especi cas de un backend de base de
datos particular y serán omitidas si no se está probando ese backend. SQLite es el backend por defecto para las pruebas. Para ejecutar las pruebas con un backend diferente ver Using
another settings module.
Una vez que las pruebas nalicen, usted debe ser recibido con un mensaje que le informa si el conjunto de pruebas pasó o falló. Dado que aún no ha realizado ningún cambio en el
código de Django, todo el conjunto de pruebas debe pasar. Si obtiene fallos o errores asegúrese de que ha seguido correctamente todos los pasos anteriores . Consulte: ref: Ejecutar
pruebas unitarias para más información.
Tenga en cuenta que la última versión de Django en master no siempre es estable. Cuando se desarrolla en master, puede comprobar la integración continua de Django para determinar
si los fallos son propios de su sistema o se encuentran también presentes en la versión o cial. Si hace clic para ver una versión en particular, usted puede ver la «Matriz de
con guración», que muestra los fallos analizados por la versión de Python y el backend de la base de datos.
Nota
Para este tutorial y el ticket en el que estamos trabajando, es su ciente probar contra SQLite, sin embargo, es posible (y a veces necesario) ejecutar las pruebas
utilizando una base de datos diferente.
Trabajando en una característica
Para este tutorial, trabajaremos sobre un «falso ticket» como un caso de estudio. Estos son los datos imaginarios:
/
Puede elegir cualquier nombre que desee para la rama, por ejemplo «ticket_99999». Todos los cambios realizados en esta rama será especí co para el ticket y no afecta la copia
principal del código previamente clonado
Una buena forma de hacer esto, es escribir primero sus nuevas pruebas antes de realizar cualquier cambio en el código. Este estilo de desarrollo se llama desarrollo guiado por pruebas y
se puede aplicar tanto a proyectos completos como a parches individuales. Después de escribir sus pruebas, ejecútelas para asegurarse de que en efecto fallan (ya que aún no ha
corregido ese bug o añadido esa característica). Si sus nuevas pruebas no fallan, tendrá que arreglarlas de manera que lo hagan. Después de todo, una prueba de regresión que pasa sin
importar si un error está presente, no es muy útil en prevenir que ese error se repita en el futuro.
Navega a la carpeta tests/shortcuts/ y crea un nuevo chero llamado test_make_toast.py. Añade el siguiente código:
class MakeToastTests(SimpleTestCase):
def test_make_toast(self):
self.assertEqual(make_toast(), 'toast')
Si usted nunca había tenido que lidiar con las pruebas anteriormente, pueden parecer un poco difíciles de escribir a primera vista. Afortunadamente, las pruebas
son un tema muy importante en la programación, así que hay mucha información disponible:
Un buen primer vistazo a las pruebas de escritura para Django se puede encontrar en la documentación en: doc:/topics/testing/overview.
Inmersión en Python (un libro en línea gratis para los desarrolladores principiantes de Python) incluye una gran introducción a las pruebas unitarias.
Después de leer esos, si quieres algo un poco mas sustancioso para hincar el diente, siempre está la documentación de unittest de Python.
/
$ ./runtests.py shortcuts
If the tests ran correctly, you should see one failure corresponding to the test method we added, with this error:
If all of the tests passed, then you’ll want to make sure that you added the new test shown above to the appropriate folder and le name.
Navigate to the django/ folder and open the shortcuts.py le. At the bottom, add:
def make_toast():
return 'toast'
Now we need to make sure that the test we wrote earlier passes, so we can see whether the code we added is working correctly. Again, navigate to the Django tests/ directory and run:
/
$ ./runtests.py shortcuts
Everything should pass. If it doesn’t, make sure you correctly added the function to the correct le.
Para ejecutar todo el conjunto de pruebas de Django, cambie al directorio tests/ de Django y ejecute:
/
$ ./runtests.py
Escribiendo la documentación
This is a new feature, so it should be documented. Open the le docs/topics/http/shortcuts.txt and add the following at the end of the le:
``make_toast()``
================
.. versionadded:: 2.2
Returns ``'toast'``.
Since this new feature will be in an upcoming release it is also added to the release notes for the next version of Django. Open the release notes for the latest version in
docs/releases/, which at time of writing is 2.2.txt. Add a note under the «Minor Features» header:
:mod:`django.shortcuts`
~~~~~~~~~~~~~~~~~~~~~~~
Para obtener más información sobre escribir la documentación, incluyendo una explicación de lo que se trata el fragmento versionadded, consulte Writing documentation. Esa página
incluye también una explicación de cómo generar una copia de la documentación localmente, por lo que puede obtener una vista previa del código HTML que se generará.
/
Then display the differences between your current copy of Django (with your changes) and the revision that you initially checked out earlier in the tutorial with:
/
+:mod:`django.shortcuts`
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* The new :func:`django.shortcuts.make_toast` function returns ``'toast'``.
+
:mod:`django.contrib.admin`
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Cuando hayas terminado de revisar el parche presiona q para volver a la línea de comandos. Si el contenido del parche se veía bien es tiempo de consumar los cambios.
/
$ git commit
Esto abre un editor de texto para escribir el mensaje del commit. Sigue las guías para mensajes del commit y escribe un mensaje como:
Fixed #99999 -- Added a shortcut function to make toast.
/
Puedes crear una solicitud de pull visitando La página GitHub de Django. Vas a ver tu rama en «Your recently pushed branches». Has clic en «Compare & pull request».
Por favor no lo hagas para este tutorial, pero en la siguiente página muestra una vista previa del parche, deberías hacer clic en «Create pull request».
Próximos pasos
¡Enhorabuena, ha aprendido cómo hacer una solicitud de pull a Django! Encontrará detalles de técnicas más avanzadas que puede necesitar en Working with Git and GitHub.
Ahora puedes dar un buen uso a esas habilidades ayudando a mejorar la base de código de Django.
Debe asegurarse de leer la documentación de Django sobre reclamar tickets y enviar parches. Esta incluye la etiqueta de Trac, cómo reclamar tickets para uno mismo, el estilo
esperado de codi cación para parches y muchos otros detalles importantes.
Las personas que colaboran por primera vez también deben leer la documentación para los colaboradores principiantes de Django. Tiene muchos buenos consejos para aquellos de
nosotros que somos nuevos en esto de colaborar con Django.
Después de ellos, si todavía quiere más información sobre cómo contribuir, siempre se puede navegar por el resto de la documentación de Django sobre cómo contribuir. Este
contiene un montón de información útil y debe ser su primera fuente para responder a cualquier pregunta que pueda tener.
If you just want to get started already (and nobody would blame you!), try taking a look at the list of easy tickets that need patches and the easy tickets that have patches which need
improvement. If you’re familiar with writing tests, you can also look at the list of easy tickets that need tests. Remember to follow the guidelines about claiming tickets that were
mentioned in the link to Django’s documentation on claiming tickets and submitting patches.
Django parece ser un framework MVC, pero ustedes llaman al Controlador «vista», y a la Vista «plantilla». ¿Cómo es que no usan los nombres estándares?
¿Por qué escribieron todo Django desde cero en vez de usar otras librerías de Python?
FAQ: Instalación
¿Cómo comienzo?
¿Cómo hago que una variable esté disponible para todas mis plantillas?
¿Cómo puedo ver las consultas SQL plano que Django está ejecutando?
¿Cómo añado opciones especí cas de la base de datos a mis sentencias CREATE TABLE, tales como establecer MyISAM como el tipo de tabla?
No puedo ingresar. Cuando ingreso un usuario y contraseña válidos, me muestra de nuevo la página de inicio de sesión sin ningún mensaje de error.
No puedo ingresar. Cuando uso un usuario y contraseña válidos, me muestra la página de inicio de sesión de nuevo con un mensaje de error de «Por favor introduzca el usuario
y contraseña correctos».
¿Cómo jo automáticamente el valor de un campo al último usuario que editó el objeto en el sitio administrativo?
¿Cómo limito el acceso en el sitio administrativo de manera que los objetos solo puedan ser modi cados por los usuarios que los crearon?
Las CSS e imágenes de mi sitio administrativo se muestran bien mientras uso el servidor de desarrollo, pero no se muestran cuando uso mod_wsgi.
¡El sitio administrativo generado de forma dinámica se ve feo! ¿Cómo puedo modi carlo?
Presenté un parche en el sistema de tickets hace varias semanas. ¿Por qué lo ignoran?
Miscelánea
FAQ: General
Al mismo tiempo, los desarrolladores de la web World Online han sido consistentemente perfeccionistas cuando se trata de seguir las mejores prácticas para el desarrollo web.
En el otoño de 2003, los desarrolladores de World Online (Adrian Holovaty y Simon Willison) abandonaron PHP y comenzaron a usar Python para desarrollar sus sitios web. A medida que
creaban sitios altamente interactivos e intensivos como Lawrence.com, comenzaron a extraer un framework de desarrollo Web genérico que les permitió crear aplicaciones Web de
forma cada vez más rápida. Ellos modi caron este framework constantemente, añadiendo mejoras a lo largo de dos años.
En el verano de 2005, World Online decidió distribuir libremente el código del software resultante, Django. Django no sería posible sin una gran cantidad de proyectos de código abierto,
Apache, Python y PostgreSQL por mencionar algunos – y estamos emocionados de aportar algo a la comunidad de código abierto.
Django usa una arquitectura tipo «nada compartido» lo cual signi ca que puede agregar hardware en cualquier nivel, servidores de base de datos, de caché o Web/Aplicaciones.
El framework separa limpiamente componentes como la capa de base de datos y la capa de la aplicación. Además, se distribuye con un simple pero poderoso framework de caché.
En nuestra interpretación de MVC, la «vista» describe el dato que es presentado al usuario. No es necesariamente cómo se ve el dato, sino qué dato se muestra. La vista describe cuál
dato ve, no cómo lo ve. Es una distinción sutil.
Así pues, en nuestro caso, una «vista» es la función de callback en Python para una URL en particular, porque esta función callback describe cuál dato es presentado.
Además, es sensato separar el contenido de la presentación que es donde entran las plantillas. En Django, una «vista» describe cual dato es presentado, pero una vista normalmente lo
delega a una plantilla, la cual describe cómo se presenta el dato.
Entonces ¿donde entra el «controlador»? En el caso de Django, es probable que en el mismo framework: la maquinaria que envía una petición a la vista apropiada, de acuerdo a la
con guración de URL de Django.
Si busca acrónimos, usted podría decir que Django es un framework «MTV», esto es «modelo», «plantilla» y «vista». Ese desglose tiene mucho más sentido.
At the end of the day, it comes down to getting stuff done. And, regardless of how things are named, Django gets stuff done in a way that’s most logical to us.
¿Por qué escribieron todo Django desde cero en vez de usar otras librerías de Python?
Cuando Django se escribió originalmente, Adrian y Simon pasaron bastante tiempo explorando los diversos frameworks web de Python disponibles.
Somos exigentes, podrían incluso llamarnos perfeccionistas (con las fechas límites.)
Con el paso del tiempo, nos topamos con librerías de código abierto que hacían cosas que ya habíamos implementado. Era reconfortante ver a otras personas resolviendo problemas
similares de maneras similares, pero era demasiado tarde para integrar código externo: Ya habíamos escrito, probado e implementado fragmentos de nuestro propio framework en varias
con guraciones de producción y que nuestro propio código satis zo nuestras necesidades de maravilla.
Sin embargo, en la mayoría de los casos encontramos que los frameworks y herramientas inevitablemente tenían algún tipo de error fatal fundamental que nos hacía remilgar. Ninguna
herramienta se adaptaba 100% a nuestra losofía.
Por ejemplo, no tiene mucho sentido comparar Django con algo como Drupal porque Django es algo que usas para crear cosas como Drupal.
Yes, Django’s automatic admin site is fantastic and timesaving – but the admin site is one module of Django the framework. Furthermore, although Django has special conveniences for
building «CMS-y» apps, that doesn’t mean it’s not just as appropriate for building «non-CMS-y» apps (whatever that means!).
Because the documentation is stored in revision control, you can browse documentation changes just like you can browse code changes.
Técnicamente, la documentación en el sitio de Django es generada a partir de la última versión de desarrollo de esos documentos reST, así que la documentación en el sitio de Django
podría ofrecer más información que los documentos que vienen con la última versión de Django.
Si su guía de estilo de referencias requiere un nombre de editor, use «Django Software Foundation».
Si necesita una fecha de publicación, use el año de lanzamiento de la versión que está consultando (por ejemplo, 2013 para v1.5)
FAQ: Instalación
¿Cómo comienzo?
1. Descargue el código.
3. Revise el tutorial.
For a development environment – if you just want to experiment with Django – you don’t need to have a separate Web server installed or database server.
Django comes with its own lightweight development server. For a production environment, Django follows the WSGI spec, PEP 3333, which means it can run on a variety of web
servers. See Deploying Django for more information.
Django runs SQLite by default, which is included in Python installations. For a production environment, we recommend PostgreSQL; but we also o cially support MariaDB, MySQL, SQLite,
and Oracle. See Supported Databases for more information.
Para cada versión de Python, sólo la última micro-version (A.B.C) es o cialmente soportada. Puede encontrar la última micro-versión de cada serie en la Página de descarga de Python
<https://www.python.org/downloads/>.
Typically, we will support a Python version up to and including the rst Django LTS release whose security support ends after security support for that version of Python ends. For
example, Python 3.3 security support ended September 2017 and Django 1.8 LTS security support ended April 2018. Therefore Django 1.8 is the last version to support Python 3.3.
Dado que las nuevas versiones de Python son a menudo más rápidas, tienen más funcionalidades, y mejor soporte, la última versión de Python 3 es recomendada.
You don’t lose anything in Django by using an older release, but you don’t take advantage of the improvements and optimizations in newer Python releases. Third-party applications for
use with Django are free to set their own version requirements.
The environment variable DJANGO_SETTINGS_MODULE is set to a fully-quali ed Python module (i.e. «mysite.settings»).
La única excepción es que: si usted utiliza una librería de base de datos diferente, no logrará utilizar el sitio administrativo generado automáticamente de Django. Esa aplicación se
acopla a la capa de base de datos de Django.
1. En el archivo de con guraciones, tendrá que de nir: setting:MEDIA_ROOT como la ruta completa para un directorio donde le gustaría que Django guardará los archivos subidos.
(Por razones de rendimiento, estos archivos no se guardan en la base de datos.) De na MEDIA_URL como la dirección URL pública de base de ese directorio. Asegúrese de que
este directorio tenga permisos de escritura por parte de la cuenta de usuario del servidor Web.
2. Añada la ImageField a su modelo, de niendo la opción upload_to para especi car un subdirectorio de MEDIA_ROOT a utilizar para los archivos subidos.
3. Todo lo que se guardará en su base de datos es una ruta de acceso al archivo (relativa a MEDIA_ROOT). Usted probablemente querrá utilizar el atributo de conveniencia url
proporcionado por Django. Por ejemplo, si su ImageField se llama mug_shot, usted puede obtener la ruta absoluta a su imagen en una plantilla con {{
object.mug_shot.url }}.
¿Cómo hago que una variable esté disponible para todas mis plantillas?
Sometimes your templates all need the same thing. A common example would be dynamically generated menus. At rst glance, it seems logical to add a common dictionary to the
template context.
The best way to do this in Django is to use a RequestContext. Details on how to do this are here: Using RequestContext.
FAQ: Obteniendo ayuda
If you can’t nd an answer, please take a few minutes to formulate your question well. Explaining the problems you are facing clearly will help others help you. See the StackOver ow
guide on asking good questions.
The Django Forum section «Using Django». This is for web-based discussions.
The #django IRC channel on the Freenode IRC network. This is for chat-based discussions. If you’re new to IRC, see the Freenode documentation for different ways to connect.
In all these channels please abide by the Django Code of Conduct. In summary, being friendly and patient, considerate, respectful, and careful in your choice of words.
Para combatir el problema del spam, cuando usted se une a la lista de correos electrónicos de django-users, nosotros controlamos manualmente el primer mensaje que usted envía a la
lista. Esto signi ca que los spammers son capturados, pero también quiere decir que su primera pregunta toma más tiempo en ser respondida. Pedimos disculpas por cualquier
inconveniente que esta política pueda causar.
As with most open-source projects, the folks on these channels are volunteers. If nobody has answered your question, it may be because nobody knows the answer, it may be because
nobody can understand the question, or it may be that everybody that can help is busy.
You can also try asking on a different channel. But please don’t post your question in all three channels in quick succession.
You might notice we have a second mailing list, called django-developers. This list is for discussion of the development of Django itself. Please don’t email support questions to this
mailing list. Asking a tech support question there is considered impolite, and you will likely be directed to ask on django-users.
Due to the sensitive nature of security issues, we ask that if you think you have found a security problem, please don’t post a message on the forum, IRC, or one of the public mailing lists.
Django has a policy for handling security issues; while a defect is outstanding, we would like to minimize any damage that could be in icted through public knowledge of that defect.
FAQ: Bases de Datos y modelos
¿Cómo puedo ver las consultas SQL plano que Django está ejecutando?
Make sure your Django DEBUG setting is set to True. Then do this:
connection.queries sólo está disponible si: setting:DEBUG está jada en True. Es una lista de diccionarios en el orden de ejecución de la consulta. Cada diccionario tiene lo
siguiente:
connection.queries incluye todas las sentencias SQL: INSERTs, UPDATES, SELECTs, etc. Cada vez que su aplicación accede a la base de datos, la consulta será registrada.
Si usted está utilizando bases de datos múltiples, usted puede utilizar la misma interfaz en cada miembro del diccionario connections:
If you need to clear the query list manually at any point in your functions, call reset_queries(), like this:
Si no le importa borrar los datos, la utilidad manage.py de su proyecto tiene una opción flush para restablecer la base de datos al estado en que estaba inmediatamente después de
que migrate fue ejecutado.
But this isn’t an issue in practice, because there’s nothing stopping you from adding other constraints (using the unique_together model option or creating the constraint directly in
your database), and enforcing the uniqueness at that level. Single-column primary keys are needed for things such as the admin interface to work; e.g., you need a single value to specify
an object to edit or delete.
You can take a look on the wiki page which discusses some projects.
¿Cómo añado opciones especí cas de la base de datos a mis sentencias CREATE TABLE, tales como
establecer MyISAM como el tipo de tabla?
Tratamos de evitar añadir casos especiales en el código de Django para ajustar todas las opciones especí cas de base de datos como el tipo de tabla, etc. Si desea usar cualquiera de
estas opciones, cree una migración con una operación RunSQL que contenga sentencias ALTER TABLE que hagan lo que usted quiere hacer.
Por ejemplo, si está usando MySQL y quiere que sus tablas usen el tipo de tabla MyISAM, use la siguiente sentencia SQL:
No puedo ingresar. Cuando ingreso un usuario y contraseña válidos, me muestra de nuevo la página de
inicio de sesión sin ningún mensaje de error.
Las cookies de inicio de sesión no se establecen correctamente, porque el dominio de las mismas enviado por Django no es igual al dominio del navegador. Intenta ajustar la opción
SESSION_COOKIE_DOMAIN para igualar el dominio. Por ejemplo, si te diriges a «https://www.example.com/admin/» en tu navegador, debes jar SESSION_COOKIE_DOMAIN =
'www.example.com'.
No puedo ingresar. Cuando uso un usuario y contraseña válidos, me muestra la página de inicio de sesión
de nuevo con un mensaje de error de «Por favor introduzca el usuario y contraseña correctos».
Si está seguro de que su nombre de usuario y contraseña son correctos, asegúrase de que la cuenta de usuario tenga is_active y is_staff jados como True. El sitio administrativo
solo permite el acceso a los usuarios que tengan ambos campos en True.
¿Cómo jo automáticamente el valor de un campo al último usuario que editó el objeto en el sitio
administrativo?
La clase ModelAdmin proporciona métodos de personalización que le permiten transformar un objeto al ser guardado usando los detalles de la petición. Mediante la extracción del
usuario actual desde la petición y personalizando el método save_model(), usted puede actualizar un objeto para que muestre el usuario que lo editó. Para ver ejemplos consulte la
documentación de los métodos del ModelAdmin.
¿Cómo limito el acceso en el sitio administrativo de manera que los objetos solo puedan ser modi cados
por los usuarios que los crearon?
La clase ModelAdmin también proporciona métodos de personalización que le permite controlar la visibilidad y edición de objetos en el sitio administrativo. Mediante el mismo truco de
extraer el usuario de la petición, los métodos get_queryset() y has_change_permission() se pueden usar para controlar la visibilidad y la edición de los objetos en el sitio
administrativo.
Las CSS e imágenes de mi sitio administrativo se muestran bien mientras uso el servidor de desarrollo, pero
no se muestran cuando uso mod_wsgi.
Consulte Sirviendo los archivos del sitio administrativo en la documentación «Cómo usar Django con mod_wsgi?».
Por ejemplo, si su list_filter incluye sitios y solo hay un sitio en su base de datos, no mostrará un ltro «Site». En ese caso, ltrar por sitio no tendría sentido.
If you want more exibility than is feasible by tweaking the auto-generated forms, feel free to write custom views for the admin. The admin is powered by Django itself, and you can write
custom views that hook into the authentication system, check permissions and do whatever else they need to do.
Si desea personalizar la apariencia de la interfaz del sitio administrativo, lea la siguiente pregunta.
¡El sitio administrativo generado de forma dinámica se ve feo! ¿Cómo puedo modi carlo?
A nosotros nos gusta, pero si a usted no, puede modi car la presentación del sitio administrativo editando las hojas de estilo CSS y/o los archivos de imágenes asociados. El sitio está
construido usando HTML semántico y personalizaciones de CSS, así que cualquier cambio que quiera realizar sería posible editando las hojas de estilo.
On mobile and tablet devices, the admin provides a responsive experience for web standards compliant browsers. This includes the major browsers on both Android and iOS.
Depending on feature support, there may be minor stylistic differences between browsers. These are considered acceptable variations in rendering.
FAQ: Aportando código
Presenté un parche en el sistema de tickets hace varias semanas. ¿Por qué lo ignoran?
¡No se preocupe: No lo estamos ignorando!
Es importante entender que existe una diferencia entre «un ticket siendo ignorado» y «un ticket que aún no ha sido atendido». El sistema de tickets de Django contiene cientos de tickets
abiertos, de diferentes grados de impacto en la funcionalidad del usuario nal y que los desarrolladores de Django necesitan revisar y priorizar.
Además de eso: las personas que trabajan en Django son todos voluntarios. Como resultado, el tiempo que tenemos para trabajar en el framework es limitado y variará de semana en
semana dependiendo de nuestro tiempo libre. Si estamos ocupado, es posible que no podamos emplear tanto tiempo en Django como quisiéramos.
La mejor forma de asegurarse de que los tickets no se queden en el camino a ser revisados es que sea muy fácil tanto entender el problema como comprobar el parche, incluso para
alguien que puede no estar familiarizado con esa área del código:
¿Existen instrucciones claras sobre cómo reproducir el bug? Si esto afecta alguna dependencia (como Pillow), un módulo de contribución o una base de datos especí ca ¿son lo
su cientemente claras esas instrucciones incluso para alguien que no está familiarizado con ello?
Si existen varios parches adjuntados al ticket, ¿se tiene claro qué hace cada uno, cuáles pueden ser ignorados y cuáles son importantes?
¿El parche contiene pruebas unitarias? Si no ¿existe una muy clara explicación de por qué no? Una prueba expresa de forma resumida cuál es el problema y muestra que el parche
realmente lo corrige.
Si su parche no tiene posibilidad de ser incluido en Django, no lo ignoraremos, simplemente cerraremos el ticket. Así que si su ticket todavía permanece abierto, no signi ca que lo
estamos ignorando; es solo que no hemos tenido tiempo aún de revisarlo.
Los recordatorios gentiles por IRC también pueden funcionar, de nuevo, estratégicamente cronometrado si es posible. Por ejemplo, durante un sprint de corrección de errores sería un
buen momento.
Otra manera de obtener tracción es colocar muchos tickets relacionados juntos. Cuando alguien se siente a revisar un bug en un área que no ha tocado por un tiempo, puede tomarle
varios minutos recordar todos los detalles de como esa área de código funciona. Si recolectas muchos errores pequeños juntos relacionados en un mismo grupo, los conviertes en un
objetivo atractivo, así el costo de revisar un área de código se puede propagar sobre varios tickets.
Por favor abstenerse de enviar correos a cualquiera personal o repetidamente, levantando la misma problemática una y otra vez. Este tipo de comportamiento no hará que gane más
atención. De nitivamente no la atención que necesitas en orden de que su problemática sea resuelta
Uno de los criterios usados para priorizar la corrección de errores es el número de personas que son afectadas por un determinado bug. Los bugs que tienen el potencial de afectar a
muchas personas generalmente tienen mayor prioridad respecto a los casos extremos.
Another reason that bugs might be ignored for while is if the bug is a symptom of a larger problem. While we can spend time writing, testing and applying lots of little patches, sometimes
the right solution is to rebuild. If a rebuild or refactor of a particular component has been proposed or is underway, you may nd that bugs affecting that component will not get as much
attention. Again, this is a matter of prioritizing scarce resources. By concentrating on the rebuild, we can close all the little bugs at once, and hopefully prevent other little bugs from
appearing in the future.
Whatever the reason, please keep in mind that while you may hit a particular bug regularly, it doesn’t necessarily follow that every single Django user will hit the same bug. Different users
use Django in different ways, stressing different parts of the code under different conditions. When we evaluate the relative priorities, we are generally trying to consider the needs of the
entire community, instead of prioritizing the impact on one particular user. This doesn’t mean that we think your problem is unimportant – just that in the limited time we have available,
we will always err on the side of making 10 people happy rather than making a single person happy.
Localización y resolución de problemas
Esta página contiene algunos consejos sobre los errores y problemas que se encuentran comúnmente durante el desarrollo de las aplicaciones de Django.
Permisos de macOS
Si está utilizando macOS, podría ver el mensaje «permiso denegado» cuando intente ejecutar django-admin. Esto se debe a que en los sistemas basados en Unix como macOS, un
archivo se debe marcar como «ejecutable» antes de que se pueda ejecutar como programa. Para hacer esto, abra Terminal.app y vaya (utilizando el comando cd) al directorio donde
django-admin está instalado, después ejecute el comando sudo chmod +x django-admin.
Miscelánea
La solución depende principalmente del contexto, sin embargo, aquí hay dos di cultades comunes que producen este error:
Su con guración regional del sistema puede ser una localización ASCII predeterminada, como la localización «C» en sistemas similares a UNIX (se puede comprobar con el
comando locale). Si es así, consulte por favor la documentación del sistema para aprender cómo usted puede cambiar esta a una localización UTF-8.
Recursos relacionados:
Unicode en Django
https://wiki.python.org/moin/UnicodeDecodeError
Glosario de términos
modelo concreto
Un modelo no abstracto (abstract=False).
campo
Un atributo en un modelo; el campo dado suele extrapolarse directamente a una sola columna de la base de datos.
Ve Models.
vista genérica
Una función view de orden superior que provee una implementación abstracta/genérica a partir un modismo o patrón común encontrado en una vista de desarrollo.
Ve Class-based views.
modelo
Ve Models.
MTV
«Modelo-plantilla-vista»; un patrón de software, similar en estilo a MVC, pero una mejor descripción de la forma en que Django funciona.
MVC
Modelo-vista-controlador; un patrón de software. Django sigue MVC en cierta medida.
proyecto
Un paquete Python – e.g: una carpeta de código – que contiene todos los ajustes para una instancia de Django. Esto podría incluir la con guración de la base de datos, opciones
especí cas de Django y ajustes especí cos de las aplicaciones.
propiedad
También conocidos como «atributos gestionados» , y una funcionalidad de Python desde la versión 2.2. Esta es una forma ordenada de implementar los atributos cuyo uso se parece al
acceso a los atributos, pero cuya implementación usa invocaciones a métodos.
Ver property().
queryset
Ve Making queries.
slug
Una etiqueta corta para algo, que solo contiene letras, números, guiones bajo o raya. Generalmente se usan en las URLs. Por ejemplo en una típica URL de publicación de un blog:
https://www.djangoproject.com/weblog/2008/apr/12/spring/
plantilla
Un pedazo de texto que hace de formato para representar datos. Una plantilla ayuda a abstraerse de la representación de datos de los datos en sí.
Ve Templates.
vista
Una función responsable de mostrar una página.