0% encontró este documento útil (0 votos)
5 vistas102 páginas

2020 Documentación - Django 3.1

Cargado por

chqr
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
5 vistas102 páginas

2020 Documentación - Django 3.1

Cargado por

chqr
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 102

Django 3.

Documentation

MCT: Luis Dueñas


Django 3.1
1. Contenidos de la documentación de Django
2. Documentación de Django
3. Empezando
3.1. Django de un vistazo
3.2. Guía de instalación rápida
3.3. Escribiendo su primera aplicación en Django, Parte 1
3.4. Escribiendo su primera aplicación en Django, Parte 2
3.5. Escribiendo su primera aplicación en Django, Parte 3
3.6. Escribiendo su primera aplicación en Django, Parte 4
3.7. Escribiendo su primera aplicación en Django, Parte 5
3.8. Escribiendo su primera aplicación en Django, Parte 6
3.9. Escribiendo su primera aplicación Django, Parte 7
3.10. Tutorial Avanzado - Cómo escribir aplicaciones reutilizables
3.11. Qué leer después
3.12. Escribiendo su primer parche para Django
4. FAQ de Django
4.1. FAQ General
4.2. FAQ Instalación
4.3. FAQ Usando Django
4.4. FAQ Obteniendo ayuda
4.5. FAQ Bases de Datos y modelos
4.6. FAQ El sitio administrativo
4.7. FAQ Aportando código
4.8. Localización y resolución de problemas
5. Glosario de términos
Contenidos de la documentación de Django
Empezando

Django de un vistazo

Diseñe su modelo

Instálelo

Disfrute de la API sin restricciones

Una interfaz administrativa dinámica: no es sólo andamios; es toda una casa

Diseñe sus URLs

Escriba sus vistas

Diseñe sus plantillas

Esto es sólo la super cie

Guía de instalación rápida

Instale Python

Cree una base de datos

Instale Django

Comprobando

¡Eso es todo!

Escribiendo su primera aplicación en Django, parte 1

Creando un proyecto

El servidor de desarrollo

Creando la aplicación encuestas

Escriba su primera vista

Escribiendo su primera aplicación en Django, parte 2

Con guración de la base de datos

Creando modelos

Activando los modelos

Jugando con la API

Presentando el sitio administrativo de Django

Escribiendo su primera aplicación en Django, parte 3

Información general

Escribiendo más vistas

Escriba vistas que realmente hagan algo

Levantar un error 404

Utilice el sistema de plantillas

Quitar URLs codi cadas de manera predeterminada en las plantillas

Asignando los nombres de URLs

Escribiendo su primera aplicación en Django, parte 4

Write a minimal form

Utilice vistas genéricas: Menos código es mejor

Escribiendo su primera aplicación en Django, parte 5

Presentando las pruebas automatizadas

Estrategias básicas de pruebas

Escribiendo nuestra primera prueba

Pruebe una vista

Cuando se trata de pruebas, más es mejor

Pruebas adicionales
¿Qué sigue?

Escribiendo su primera aplicación en Django, parte 6

Personalice la apariencia de su aplicación

Agregando una imagen de fondo

Escribiendo su primera aplicación Django, parte 7

Personalice el formulario del sitio administrativo

Agregando objetos relacionados

Personalice la lista de cambios del sitio administrativo

Personalice el aspecto del sitio administrativo

Personalice la página del índice del sitio administrativo

¿Qué sigue?

Tutorial Avanzado: Cómo escribir aplicaciones reutilizables

La reusabilidad importa

Su proyecto y su aplicación reutilizable

Instalación de algunos requisitos previos

Empaquetando su aplicación

Usando su propio paquete

Publicando su aplicación

Installing Python packages with a virtual environment

Qué leer después

Buscando documentación

Cómo está organizada la documentación

Cómo se mejora la documentación

Dónde conseguirla

Diferencias entre versiones

Escribiendo su primer parche para Django

Introducción

Código de Conducta

Instalando Git

Obtener una copia de la versión de desarrollo de Django

Ejecutando el conjunto de pruebas de Django por primera vez

Trabajando en una característica

Crear una rama para su parche

Escribiendo algunas pruebas para su reporte

Escribiendo el código para su ticket

Ejecutando el conjunto de pruebas de Django por segunda vez

Escribiendo la documentación

Previsualizar sus cambios

Consumar los cambios en el parche

Empujar el commit y hacer una solicitud de pull

Próximos pasos

Using Django

How to install Django

Install Python

Install Apache and mod_wsgi

Get your database running

Install the Django code


Models and databases

Models

Making queries

Aggregation

Search

Managers

Performing raw SQL queries

Database transactions

Multiple databases

Tablespaces

Database access optimization

Database instrumentation

Examples of model relationship API usage

Handling HTTP requests

URL dispatcher

Writing views

View decorators

File Uploads

Django shortcut functions

Generic views

Middleware

How to use sessions

Working with forms

HTML forms

Django’s role in forms

Forms in Django

Building a form

More about Django Form classes

Working with form templates

Further topics

Templates

The Django template language

Support for template engines

Class-based views

Introduction to class-based views

Built-in class-based generic views

Form handling with class-based views

Using mixins with class-based views

Basic examples

Usage in your URLconf

Subclassing generic views

Migrations

The Commands

Backend Support

Work ow

Dependencies

Migration les
Adding migrations to apps

Reversing migrations

Historical models

Considerations when removing model elds

Data Migrations

Squashing migrations

Serializing values

Supporting multiple Django versions

Managing les

Using les in models

The File object

File storage

Testing in Django

Writing and running tests

Testing tools

Advanced testing topics

User authentication in Django

Overview

Installation

Usage

Django’s cache framework

Setting up the cache

The per-site cache

The per-view cache

Template fragment caching

The low-level cache API

Downstream caches

Using Vary headers

Controlling cache: Using other headers

Order of MIDDLEWARE

Conditional View Processing

The condition decorator

Shortcuts for only computing one value

Using the decorators with other HTTP methods

Comparison with middleware conditional processing

Cryptographic signing

Protecting the SECRET_KEY

Using the low-level API

Sending email

Quick example

send_mail()

send_mass_mail()

mail_admins()

mail_managers()

Examples

Preventing header injection

The EmailMessage class


Email backends

Con guring email for development

Internationalization and localization

Overview

De nitions

Logging

A quick logging primer

Using logging

Con guring logging

Django’s logging extensions

Django’s default logging con guration

Pagination

The Paginator class

Example

Paginating a ListView

Using Paginator in a view function

Security in Django

Cross site scripting (XSS) protection

Cross site request forgery (CSRF) protection

SQL injection protection

Clickjacking protection

SSL/HTTPS

Host header validation

Referrer policy

Session security

User-uploaded content

Additional security topics

Performance and optimization

Introduction

General approaches

Caching

Understanding laziness

Databases

HTTP performance

Template performance

Using different versions of available software

Serializing Django objects

Serializing data

Deserializing data

Serialization formats

Natural keys

Django settings

The basics

Designating the settings

Default settings

Using settings in Python code

Altering settings at runtime


Security

Available settings

Creating your own settings

Using settings without setting DJANGO_SETTINGS_MODULE

Signals

Listening to signals

De ning and sending signals

Disconnecting signals

System check framework

Writing your own checks

External packages

Local avor

Comments

Formtools

Asynchronous support

Async views

Async safety

Async adapter functions

«How-to» guides

Autenticación con el uso de REMOTE_USER

Con guración

Usando REMOTE_USER en paginas de ingreso solamente

Writing custom django-admin commands

Aceptar los argumentos opcionales

Management commands and locales

Testing

Overriding commands

Objetos de Comando

Escribiendo campos del modelo personalizado

Introducción

Fundamentos teóricos

Writing a eld subclass

Writing a FileField subclass

Búsquedas personalizadas

A lookup example

A transformer example

Escribiendo una búsqueda abs__lt e ciente

A bilateral transformer example

Escribiendo implementaciones alternativas existentes para las búsquedas

How Django determines the lookups and transforms which are used

Custom template backend

Custom backends

Debug integration for custom engines

Custom template tags and lters

Code layout

Escribir ltros plantilla de personalizada

Escribir etiquetas de plantilla de personalizadas


Creación de sistema de almacenamiento personalizado

Deploying Django

How to deploy with WSGI

How to deploy with ASGI

Deployment checklist

Upgrading Django to a newer version

Required Reading

Dependencies

Resolving deprecation warnings

Installation

Testing

Deployment

Error reporting

Reportes de correo electrónico

Filtering error reports

Providing initial data for models

Providing initial data with migrations

Providing data with xtures

Integrating Django with a legacy database

Give Django your database parameters

Auto-generate the models

Install the core Django tables

Test and tweak

Outputting CSV with Django

Using the Python CSV library

Using the template system

Other text-based formats

Outputting PDFs with Django

Install ReportLab

Write your view

Other formats

Overriding templates

Overriding from the project’s templates directory

Overriding from an app’s template directory

Extending an overridden template

Managing static les (e.g. images, JavaScript, CSS)

Con guring static les

Serving static les during development

Serving les uploaded by a user during development

Testing

Deployment

Learn more

Deploying static les

Serving static les in production

Learn more

How to install Django on Windows

Instale Python
About pip

Setting up a virtual environment

Instale Django

Common pitfalls

Writing database migrations

Data migrations and multiple databases

Migrations that add unique elds

Controlling the order of migrations

Migrating data between third-party apps

Changing a ManyToManyField to use a through model

Changing an unmanaged model to managed

FAQ de Django

FAQ: General

¿Por qué existe este proyecto?

¿Qué signi ca «Django» y cómo se pronuncia?

¿Es estable Django?

¿Se puede escalar Django?

¿Quién está detrás de esto?

¿Cómo se licencia Django?

Why does Django include Python’s license le?

¿Qué sitios usan Django?

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?

El <Framework X> tiene la <funcionalidad Y> – ¿por qué Django no?

¿Por qué escribieron todo Django desde cero en vez de usar otras librerías de Python?

¿Django es un Sistema de Gestión de Contenidos (CMS)?

¿Cómo puedo descargar la documentación de Django para leerla sin conexión?

¿Cómo cito a Django?

FAQ: Instalación

¿Cómo comienzo?

¿Cuáles son los requisitos previos de Django?

¿Qué versión de Python puedo usar con Django?

¿Qué versión de Python debería usar con Django?

¿Debería usar la versión estable o la de desarrollo?

FAQ: Usando Django

Why do I get an error about importing DJANGO_SETTINGS_MODULE?

No puedo soportar su lenguaje de plantillas. ¿Tengo que usarlo?

¿Tengo que utilizar su capa del modelo y la capa de base de datos?

¿Cómo uso los campos de imágenes y archivos?

¿Cómo hago que una variable esté disponible para todas mis plantillas?

FAQ: Obteniendo ayuda

¿Cómo hago X cosa?¿Por qué Y no funciona?¿Dónde puedo obtener ayuda?

Why hasn’t my message appeared on django-users?

Nobody answered my question! What should I do?

¡Creo que he hallado un bug! ¿Qué debo hacer?

¡Creo que he hallado un problema de seguridad! ¿Qué debo hacer?

FAQ: Bases de Datos y modelos

¿Cómo puedo ver las consultas SQL plano que Django está ejecutando?
¿Puedo usar Django con una base de datos ya existente?

Si realizo cambios a un modelo, ¿cómo actualizo la base de datos?

¿Los modelos de Django soportan claves primarias en columnas múltiples?

¿Soporta Django bases de datos NoSQL?

¿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?

FAQ: El sitio administrativo

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.

Mi «list_ lter» contiene un ManyToManyField, pero el ltro no se visualiza.

Algunos objetos no están apareciendo en el sitio administrativo.

¿Cómo puedo personalizar la funcionalidad de la interfaz del sitio administrativo?

¡El sitio administrativo generado de forma dinámica se ve feo! ¿Cómo puedo modi carlo?

¿Qué navegadores están soportados para usar el sitio administrativo?

FAQ: Aportando código

¿Cómo puedo empezar a aportar código para Django?

Presenté un parche en el sistema de tickets hace varias semanas. ¿Por qué lo ignoran?

¿Cómo y cuando debo recordarle al equipo sobre un parche que me importa?

¡Pero les he recordado varias veces y siguen ignorando mi parche!

Localización y resolución de problemas

Problemas ejecutando django-admin

Miscelánea

API Reference

Applications

Projects and applications

Con guring applications

Application con guration

Application registry

Initialization process

System check framework

API reference

Builtin tags

Core system checks

contrib app checks

Built-in class-based views API

Base views

Generic display views

Generic editing views

Generic date views

Class-based views mixins

Class-based generic views - attened index

Speci cation

Base vs Generic views

Clickjacking Protection

An example of clickjacking
Preventing clickjacking

How to use it

Limitations

contrib packages

The Django admin site

django.contrib.auth

The contenttypes framework

The atpages app

GeoDjango

django.contrib.humanize

The messages framework

django.contrib.postgres

The redirects app

The sitemap framework

The «sites» framework

The staticfiles app

The syndication feed framework

admin

auth

contenttypes

flatpages

gis

humanize

messages

postgres

redirects

sessions

sites

sitemaps

syndication

Other add-ons

Cross Site Request Forgery protection

How to use it

Rejected requests

How it works

Caching

Testing

Limitations

Edge cases

Contrib and reusable apps

Settings

Frequently Asked Questions

Databases

General notes

PostgreSQL notes

MariaDB notes
MySQL notes

SQLite notes

Oracle notes

Subclassing the built-in database backends

Using a 3rd-party database backend

django-admin and manage.py

Usage

Available commands

Commands provided by applications

Default options

Extra niceties

Running management commands from your code

Output redirection

Django Exceptions

Django Core Exceptions

URL Resolver exceptions

Database Exceptions

Http Exceptions

Transaction Exceptions

Testing Framework Exceptions

Python Exceptions

File handling

The File object

File storage API

Uploaded Files and Upload Handlers

Forms

The Forms API

Form elds

Model Form Functions

Formset Functions

The form rendering API

Widgets

Form and eld validation

Middleware

Available middleware

Middleware ordering

Migration Operations

Schema Operations

Special Operations

Writing your own

Models

Model eld reference

Field attribute reference

Model index reference

Constraints reference

Model _meta API

Related objects reference


Model class reference

Model Meta options

Model instance reference

QuerySet API reference

Lookup API reference

Query Expressions

Conditional Expressions

Database Functions

Paginator

Paginator class

Page class

Exceptions

Request and response objects

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

Core Settings Topical Index

Signals

Model signals

Management signals

Request/response signals

Test signals

Database Wrappers

Templates

The Django template language

Built-in template tags and lters

The Django template language: for Python programmers

TemplateResponse and SimpleTemplateResponse

SimpleTemplateResponse objects

TemplateResponse objects

The rendering process

Using TemplateResponse and SimpleTemplateResponse

Unicode data
Creating the database

General string handling

Models

Templates

Files

Form submission

django.urls utility functions

reverse()

reverse_lazy()

resolve()

get_script_prefix()

django.urls functions for use in URLconfs

path()

re_path()

include()

register_converter()

django.conf.urls functions for use in URLconfs

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

How validators are run

Built-in validators

Built-in Views

Serving les in development

Error views

Documentación meta y miscelánea

Estabilidad de la API
Qué signi ca «estable»

APIs estables

Excepciones

Filosofía de diseño

En general

Modelos

API de base de datos

Diseño de URLs

Sistema de plantillas

Vistas

Framework caché

Distribuciones de terceros de Django

Para los distribuidores

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

Contribuyendo con Django

Consejos para los nuevos colaboradores

Cómo informar de errores y solicitar funcionalidades

Clasi cando tickets

Writing code

Writing documentation

Localizando Django

Con rmando código

Mailing lists

django-users

django-core-mentorship
django-developers

django-i18n

django-announce

django-updates

Organization of the Django Project

Principles

Core team

Technical board

Changing the organization

Django’s security policies

Reporting security issues

Supported versions

How Django discloses security issues

Who receives advance noti cation

Requesting noti cations

Django’s release process

O cial releases

Release cadence

Deprecation policy

Supported versions

Release process

Django Deprecation Timeline

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

The Django source code repository

High-level overview

The master branch

Stable branches

Etiquetas

How is Django Formed?

Información general

Prerequisites

Pre-release tasks

Preparing for release

Actually rolling the release

Making the release(s) available to the public


Post-release

New stable branch tasks

Notes on setting the VERSION tuple

Indices, glosario y tablas


Índice

Índice de Módulos

Glosario de términos
Documentación de Django
Todo lo que necesita saber sobre Django.

Los primeros pasos


¿Es usted nuevo en Django o con la programación? ¡Este es el lugar para comenzar!

Desde cero: Visión general | Instalación

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.

Reporte bugs con Django en nuestro rastreador de tickets.

Como está organizada la documentación


Django tiene mucha documentación. Una descripción general de alto nivel de cómo se organiza le ayudará a saber dónde buscar ciertas cosas:

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.

La capa del modelo


Django proporciona una capa de abstracción (los «modelos») para estructurar y manipular los datos de su aplicación Web. Aprenda más sobre esta a continuación:

Modelos: Introducción a los modelos | Tipos de campos | Índices | Opciones Meta | Clase Model

Querysets:Haciendo consultas | Referencia de métodos de QuerySet | Expresiones de búsqueda

Instancias de modelos: Métodos de las instancias | Accediendo a objetos relacionados

Migraciones: Introducción a las migraciones | Referencia de operaciones | SchemaEditor | Escribiendo migraciones

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:

The basics: URLconfs | View functions | Shortcuts | Decorators | Asynchronous Support

Referencia: Vistas incorporadas en Django | Objetos petición/respuesta | Objetos TemplateResponse

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

Middleware: Visión general | Clases de Middleware incorporadas

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:

Lo básico: Visión general

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.

Lo básico: Visión general | API de formularios | Campos incorporados | Widgets incorporados

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:

Ajustes: Visión general | Lista completa de ajustes

Aplicaciones: Información general

Excepciones: Visión general

django-admin y manage.py: Información general | Añadiendo comandos personalizados

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

Acciones del sitio administrativo

Generador de documentación del 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:

Información general de la seguridad

Problemas de seguridad en Django revelados

protección contra Clickjacking

Protección de Falsi cación de Petición entre Sitios

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.

Reseña sobre rendimiento y optimización

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.

Herramientas comunes para aplicaciones Web


Django ofrece múltiples herramientas que son necesarias para el desarrollo de aplicaciones Web:

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

Fuentes de redifusión (RSS/Atom)

Paginado

Framework de mensajes

Serialización

Sesiones

Mapas de sitio

Gestión de archivos estáticos

Validación de datos

Otras funcionalidades básicas


Aprenda sobre otras funcionalidades básicas del framework Django:

Procesamiento condicional de contenido

Tipos de contenido y relaciones genéricas

Páginas estáticas

Redirecciones

Señales

Framework de comprobación de sistema

El framework de sitios

Unicode en Django

El proyecto de código abierto Django


Aprenda sobre el proceso de desarrollo para el proyecto Django en sí y sobre cómo puede contribuir:

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

Filosofías de diseño: Información general

Documentación: Sobre esta documentación

Distribuciones de terceros: Visión general

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

Guía de instalación rápida

Escribiendo su primera aplicación en Django, parte 1

Escribiendo su primera aplicación en Django, parte 2

Escribiendo su primera aplicación en Django, parte 3

Escribiendo su primera aplicación en Django, parte 4

Escribiendo su primera aplicación en Django, parte 5

Escribiendo su primera aplicación en Django, parte 6

Escribiendo su primera aplicación Django, parte 7

Tutorial Avanzado: Cómo escribir aplicaciones reutilizables

Qué leer después

Escribiendo su primer parche para Django

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 

from django.db import models

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:

/ 

$ python manage.py makemigrations


$ python manage.py migrate

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.

Disfrute de la API sin restricciones


With that, you’ve got a free, and rich, Python API to access your data. The API is created on the y, no code generation necessary:
# Import the models we created from our "news" app
>>> from news.models import Article, Reporter

# No reporters are in the system yet.


>>> Reporter.objects.all()
<QuerySet []>

# Create a new Reporter.


>>> r = Reporter(full_name='John Smith')

# Save the object into the database. You have to call save() explicitly.
>>> r.save()

# Now it has an ID.


>>> r.id
1

# Now the new reporter is in the database.


>>> Reporter.objects.all()
<QuerySet [<Reporter: John Smith>]>

# Fields are represented as attributes on the Python object.


>>> r.full_name
'John Smith'

# Django provides a rich database lookup API.


>>> Reporter.objects.get(id=1)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__startswith='John')
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__contains='mith')
<Reporter: John Smith>
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Reporter matching query does not exist.

# Create an article.
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
... content='Yeah.', reporter=r)
>>> a.save()

# Now the article is in the database.


>>> Article.objects.all()
<QuerySet [<Article: Django is cool>]>

# Article objects get API access to related Reporter objects.


>>> r = a.reporter
>>> r.full_name
'John Smith'

# And vice versa: Reporter objects get API access to Article objects.
>>> r.article_set.all()
<QuerySet [<Article: Django is cool>]>

# The API follows relationships as far as you need, performing efficient


# JOINs for you behind the scenes.
# This finds all articles by a reporter whose name starts with "John".
>>> Article.objects.filter(reporter__full_name__startswith='John')
<QuerySet [<Article: Django is cool>]>

# Change an object by altering its attributes and calling save().


>>> r.full_name = 'Billy Goat'
>>> r.save()

# Delete an object with delete().


>>> r.delete()

Una interfaz administrativa dinámica: no es sólo andamios; es toda una casa


Once your models are de ned, Django can automatically create a professional, production ready administrative interface – a website that lets authenticated users add, change and delete
objects. The only step required is to register your model in the admin site:

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 

from django.contrib import admin

from . import models

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.

Diseñe sus URLs


Un esquema de URL limpio y elegante es un detalle importante en una aplicación web de alta calidad. Django fomenta un diseño de URL hermoso y no añade ningún elemento
innecesario en las URLs, como .php o .asp.

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.

Así es como se vería una URLconf para el ejemplo Reporter/Article anterior:

mysite/news/urls.py 

from django.urls import path

from . import views

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).

Escriba sus vistas


Cada vista es responsable de hacer una de dos cosas: retornar un objeto HttpResponse que incluye el contenido de la página solicitada, o levantar una excepción como Http404. El
resto depende de ti.

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

from .models import Article

def year_archive(request, year):


a_list = Article.objects.filter(pub_date__year=year)
context = {'year': year, 'article_list': a_list}
return render(request, 'news/year_archive.html', context)

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.

Diseñe sus plantillas


El código anterior carga la plantilla news/year_archive.html.

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.

Digamos que se encontró la plantilla news/year_archive.html`. Así es como podría verse:

mysite/news/templates/news/year_archive.html 

{% extends "base.html" %}

{% block title %}Articles for {{ year }}{% endblock %}

{% block content %}
<h1>Articles for {{ year }}</h1>

{% for article in article_list %}


<p>{{ article.headline }}</p>
<p>By {{ article.reporter.full_name }}</p>
<p>Published {{ article.pub_date|date:"F j, Y" }}</p>
{% endfor %}
{% endblock %}

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.
>>>

Cree una base de datos


This step is only necessary if you’d like to work with a «large» database engine like PostgreSQL, MariaDB, MySQL, or Oracle. To install such a database, consult the database installation
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.

¡Siempre consulte la documentación correspondiente a la versión de Django que está utilizando!

 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:

>>> import django


>>> print(django.get_version())
3.1

Usted puede tener instalada otra versión de 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.

Consistirá de dos partes:

Un sitio público que le permite a las personas ver sondeos y votar en ellos.

Un sitio admin que le permite añadir, modi car y borrar sondeos.

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 $):

/ 

$ python -m django --version

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.

Dónde obtener ayuda:

 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:

/ 

$ django-admin startproject mysite

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).

¿Dónde debería estar este código?

 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.

Veamos lo que el comando startproject creó:


mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py

Estos archivos son:

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:

/ 

$ python manage.py runserver

Verá la siguiente salida en la línea de comandos:

Performing system checks...

System check identified no issues (0 silenced).

You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.

agosto 13, 2020 - 15:50:53


Django version 3.1, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

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:

/ 

$ python manage.py runserver 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:

/ 

$ python manage.py runserver 0:8000

0 es un atajo para 0.0.0.0. La documentacion completa de el servidor de desarrollo se encuentra en la referencia de runserver.

Recarga automática del comando 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.

Creando la aplicación encuestas


Ahora que su entorno, un «proyecto», se ha con gurado, ya está listo para empezar a trabajar.

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.

Proyectos vs. aplicaciones

 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:

/ 

$ python manage.py startapp polls

Eso va a crear un directorio polls que se presenta de la siguiente forma:

polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py

Esta estructura de directorios almacenará la aplicación encuesta.


Escriba su primera vista
Vamos a escribir la primera vista. Abra el archivo polls/views.py y ponga el siguiente código Python en ella:

polls/views.py 

from django.http import HttpResponse

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

Incluya el siguiente código en el archivo polls/urls.py:

polls/urls.py 

from django.urls import path

from . import views

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 

from django.contrib import admin


from django.urls import include, path

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.

Cuándo utilizar include()

 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.

argumento path(): route


route es una cadena que contiene un patrón de URL. Cuando Django procesa una petición comienza por el primer patrón en urlpatterns y continua hacia abajo por la lista
comparando la URL solicitada con cada patrón hasta encontrar aquel que calza.

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/.

argumento path(): view


Cuando Django encuentra una coincidencia de expresiones regulares llama a la función de la vista especi cada con un objeto HttpRequest como primer argumento y cualquiera de los
valores «capturados» de la ruta como argumentos de palabra clave. Le daremos un ejemplo de esto en un momento.

argumento path(): kwargs


Los argumentos arbitrarios de palabra clave se pueden pasar en un diccionario a la vista destino. No vamos a utilizar esta funcionalidad de Django en el tutorial.

argumento path(): name


Dar un nombre a su URL le permite referirse a ella de forma inequívoca desde otras partes de Django sobre todo desde las plantillas. Esta potente característica le permite realizar
cambios globales en los patrones de URL de su proyecto modi cando solo un único archivo.

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.

Dónde obtener ayuda:

 If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.

Con guración de la base de datos


Ahora, abra el archivo mysite/settings.py. Es un módulo normal de Python con variables de nivel de módulo que representan la con guración de Django.

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:

ENGINE – bien sea 'django.db.backends.sqlite3', 'django.db.backends.postgresql_psycopg2', 'django.db.backends.mysql', o


'django.db.backends.oracle'. Otros backends también están disponibles.

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.

Para bases de datos distintas a SQLite

 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:

django.contrib.admin - El sitio administrativo. Usted lo utilizará dentro de poco.

django.contrib.auth– Un sistema de autenticación.

django.contrib.contenttypes– Un framework para los tipos de contenido.

django.contrib.sessions – Un framework de sesión.

django.contrib.messages – Un framework de mensajería.

django.contrib.staticfiles – Un framework para la gestión de archivos estáticos.

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:

/ 

$ python manage.py migrate

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.

Para los minimalistas

 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 

from django.db import models

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.

Activando los modelos


Ese pequeño fragmento de código de modelo le proporciona a Django mucha información. Con él Django es capaz de:

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:

/ 

$ python manage.py makemigrations polls

Usted debe ver algo similar a lo siguiente:

Migrations for 'polls':


polls/migrations/0001_initial.py
- Create model Question
- Create model Choice

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:

/ 

$ python manage.py sqlmigrate polls 0001

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;

Tenga en cuenta lo siguiente:

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:

/ 

$ python manage.py migrate


Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK

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:

Cambie sus modelos (en models.py).

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:

/ 

$ python manage.py shell

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.

Una vez que esté en el shell, explore la API de base de datos:

>>> from polls.models import Choice, Question # Import the model classes we just wrote.

# No questions are in the system yet.


>>> Question.objects.all()
<QuerySet []>

# Create a new Question.


# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

# Save the object into the database. You have to call save() explicitly.
>>> q.save()

# Now it has an ID.


>>> q.id
1

# Access model field values via Python attributes.


>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# Change values by changing the attributes, then calling save().


>>> q.question_text = "What's up?"
>>> q.save()

# objects.all() displays all the questions in the database.


>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>

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 

from django.db import models

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.

Let’s also add a custom method to this model:

polls/models.py 
import datetime

from django.db import models


from django.utils import timezone

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

# Make sure our __str__() addition worked.


>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>

# Django provides a rich database lookup API that's entirely driven by


# keyword arguments.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>

# Get the question that was published this year.


>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

# Request an ID that doesn't exist, this will raise an exception.


>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.

# Lookup by a primary key is the most common case, so Django provides a


# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>

# Make sure our custom method worked.


>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True

# 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 []>

# Create three choices.


>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)

# Choice objects have API access to their related Question objects.


>>> c.question
<Question: What's up?>

# And vice versa: Question objects get access to Choice objects.


>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3

# The API automatically follows relationships as far as you need.


# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

# Let's delete one of the choices. Use delete() for that.


>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

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.

Creando un usuario del admin


Primero tendremos que crear un usuario que pueda iniciar sesión en el sitio administrativo. Ejecute el siguiente comando:

/ 

$ python manage.py createsuperuser

Introduzca su nombre de usuario deseado y pulse enter.

Username: admin

A continuación se le solicitará su dirección de correo electrónico deseada:

Email address: [email protected]

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.

Inicie el servidor de desarrollo


El sitio administrativo de Django se activa de forma predeterminada. Vamos a iniciar el servidor de desarrollo y a explorarlo.

Si el servidor no está en marcha, inícielo de la siguiente forma:

/ 

$ python manage.py runserver

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).

Acceda al sitio administrativo


Ahora, intente iniciar sesión con la cuenta de superusuario que creó en el paso anterior. Debería ver la página de índice del sitio administrativo de Django:

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.

Haga que la aplicación encuesta se pueda modi car en el sitio administrativo


Pero ¿Dónde está nuestra aplicación encuesta? No se muestra en la página de índice del sitio administrativo.

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 

from django.contrib import admin

from .models import Question

admin.site.register(Question)

Explore la funcionalidad gratuita del sitio administrativo


Ahora que hemos registrado el modelo Question, Django sabe que se debe desplegar en la página de índice del sitio administrativo:
Haga clic en «Questions». Ahora usted está en la página «lista de cambios» para las preguntas. Esta página muestra todas las preguntas de la base de datos y le permite seleccionar una
para modi carla. Ahí está la pregunta «¿Qué pasa?» que creamos anteriormente:

Haga clic en la pregunta «¿Qué pasa?» para editarla:

Cosas a tener en cuenta aquí:

El formulario se genera automáticamente a partir del modelo 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.

La parte inferior de la página le da un par de opciones:

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.

Eliminar – Muestra una página de con rmación de eliminación.

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»

Dónde obtener ayuda:

 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:

La página de inicio del blog – muestra las últimas pocas entradas.

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.

Comentar – gestiona la publicación de comentarios en una entrada determinada.

En nuestra aplicación encuestas, vamos a tener las siguientes cuatro vistas:

La página «índice» de preguntas – muestra las últimas preguntas.

La página «de detalle» de preguntas– muestra un texto de pregunta sin resultados, pero con un formulario para votar.

Página «resultados» de preguntas – muestra los resultados de una pregunta en particular.

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.

A URL pattern is the general form of a URL - for example: /newsarchive/<year>/<month>/.

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.

Escribiendo más vistas


A continuación vamos a agregar más vistas a polls/views.py. Estas vistas son un poco diferentes porque toman un argumento:

polls/views.py 

def detail(request, question_id):


return HttpResponse("You're looking at question %s." % question_id)

def results(request, question_id):


response = "You're looking at the results of question %s."
return HttpResponse(response % question_id)

def vote(request, question_id):


return HttpResponse("You're voting on question %s." % question_id)

Una estas nuevas vistas al módulo polls.urls añadiendo las siguientes llamadas path():

polls/urls.py 
from django.urls import path

from . import views

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:

detail(request=<HttpRequest object>, question_id=34)

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.

Escriba vistas que realmente hagan algo


Cada vista es responsable de hacer una de dos cosas: retornar un objeto HttpResponse con el contenido de la página solicitada, o levantar una excepción como Http404. El resto
depende de usted.

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.

Todo Django quiere es ese objeto HttpResponse o una excepción.

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 

from django.http import HttpResponse

from .models import Question

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)

# Leave the rest of the views (detail, results, vote) unchanged

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.

Introduzca el siguiente código en esa plantilla:

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 

from django.http import HttpResponse


from django.template import loader

from .models import Question

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 

from django.shortcuts import render

from .models import Question

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.

Levantar un error 404


Ahora vamos a abordar la vista de detalle de la pregunta: la página que muestra el texto de pregunta para una encuesta determinada. Aquí está la vista:

polls/views.py 

from django.http import Http404


from django.shortcuts import render

from .models import Question


# ...
def detail(request, question_id):
try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question does not exist")
return render(request, 'polls/detail.html', {'question': question})

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 }}

le ayudará a empezar por ahora.

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 

from django.shortcuts import get_object_or_404, render

from .models import Question


# ...
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})

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 

<h1>{{ question.question_text }}</h1>


<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

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%}.

Consulte la guía de plantillas para más información sobre las plantillas.

Quitar URLs codi cadas de manera predeterminada en las plantillas


Recuerde que cuando escribimos el enlace para una pregunta en la plantilla polls/index.html, el enlace estaba parcialmente codi cado de forma predeterminada como este:

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>

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 %}:

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

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'),
...

Asignando los nombres de URLs


El proyecto tutorial solo tiene una aplicación; polls. En proyectos reales de Django, puede haber cinco, diez, veinte o más aplicaciones. ¿Cómo diferencia Django los nombres de las
URLs entre ellos? Por ejemplo, la aplicación polls tiene una vista detail, como la podría tener también una aplicación en el mismo proyecto que es para un blog. ¿Cómo hacer para
que Django sepa cual vista de aplicaciones crear para una URL cuando se utiliza la etiqueta de plantilla`` {% url%}``?
La solución es añadir espacios de nombres a su URLconf. En el archivo polls/urls.py, añada un app_name para con gurar el espacio de nombres de la aplicación:

polls/urls.py 

from django.urls import path

from . import views

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'),
]

Ahora modi que su plantilla polls/index.html desde:

polls/templates/polls/index.html 

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

para señalar la vista de detalle con espacio de nombres:

polls/templates/polls/index.html 

<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

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.

Dónde obtener ayuda:

 If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.

Write a minimal form


Vamos a actualizar nuestra plantilla de detalles de encuestas («polls/detail.html») a partir del último tutorial, de modo que la plantilla contenga un elemento HTML <form>:

polls/templates/polls/detail.html 

<h1>{{ question.question_text }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="{% url 'polls:vote' question.id %}" method="post">


{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
<input type="submit" value="Vote">
</form>

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.

`` forloop.counter`` indica cuántas veces la etiqueta for ha pasado por el bucle

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 

path('<int:question_id>/vote/', views.vote, name='vote'),

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

from .models import Choice, Question


# ...
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

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 

from django.shortcuts import get_object_or_404, render

def results(request, question_id):


question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})

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.

Ahora, cree una plantilla polls/results.html:

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 href="{% url 'polls:detail' question.id %}">Vote again?</a>

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.

Utilice vistas genéricas: Menos código es mejor


The detail() (from Tutorial 3) and results() views are very short – and, as mentioned above, redundant. The index() view, which displays a list of polls, is similar.

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.

2. Eliminar algunas de las vistas viejas e innecesarias.

3. Introducir nuevas vistas basadas en las vistas genéricas de Django.

Siga leyendo para conocer más detalles.

¿Por qué el intercambio de código?

 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.

Debe saber matemáticas básicas antes de comenzar a utilizar una calculadora.

Modi que el URLconf


Primero, abra el URLconf polls/urls.py y modifíquelo de la siguiente manera:

polls/urls.py 

from django.urls import path

from . import views

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>.

Modi que las vistas


A continuación, vamos a eliminar nuestras viejas vistas index, detail y results y en su lugar vamos a usar las vistas genéricas de Django. Para ello, abra el archivo
polls/views.py y modifíquelo de la siguiente manera:

polls/views.py 

from django.http import HttpResponseRedirect


from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic

from .models import Choice, Question

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'

def vote(request, question_id):


... # same as above, no changes needed.

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.

Dónde obtener ayuda:

 If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.

Presentando las pruebas automatizadas ¶

¿Qué son las pruebas automatizadas?


Tests are routines that check the operation of your code.

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.

El por qué necesita crear pruebas


Entonces, ¿por qué crear pruebas y por qué ahora?

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.

Las pruebas le ahorrarán tiempo

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.

Las pruebas no solo identi can los problemas, los previenen

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.

Las pruebas hacen más atractivo su código

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.

Las pruebas ayudan a los equipos a trabajar en conjunto


Los puntos anteriores están escritos desde el punto de vista de un único desarrollador que mantiene una aplicación. Las aplicaciones complejas serán mantenidas por equipos. Las
pruebas garantizan que los colegas no rompan inadvertidamente su código (y que usted no rompa el de ellos sin saber). Si quiere ganarse la vida como un programador de Django,
¡Usted debe ser bueno escribiendo pruebas!

Estrategias básicas de pruebas


Hay muchas maneras de abordar la escritura de 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.

Así que vamos a hacer eso de inmediato.

Escribiendo nuestra primera prueba

Identi camos un bug


Afortunadamente, hay un pequeño bug en la aplicación polls para que lo solucionemos de inmediato: el método Question.was_published_recently() retorna True si la
Question fue publicada en el último día (que es correcto), pero también si el campo de pub_date de Question está en el futuro (que de hecho no lo está).

Con rm the bug by using the shell to check the method on a question whose date lies in the future:

/ 

$ python manage.py shell

>>> import datetime


>>> from django.utils import timezone
>>> from polls.models import Question
>>> # create a Question instance with pub_date 30 days in the future
>>> future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30))
>>> # was it published recently?
>>> future_question.was_published_recently()
True

Puesto que las cosas en el futuro no son “recientes”, esto es claramente erróneo.

Cree una prueba para mostrar el bug


Lo que acabamos de hacer en el comando shell para detectar el problema es exactamente lo que podemos hacer en una prueba automatizada, así que vamos a convertir eso en una
prueba automatizada.

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.

Ponga lo siguiente en el archivo tests.py de la aplicación polls:

polls/tests.py 
import datetime

from django.test import TestCase


from django.utils import timezone

from .models import Question

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.

Ejecutando las pruebas


In the terminal, we can run our test:

/ 

$ python manage.py test polls

y usted verá algo como:

Creating test database for alias 'default'...


System check identified no issues (0 silenced).
F
======================================================================
FAIL: test_was_published_recently_with_future_question (polls.tests.QuestionModelTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/path/to/mysite/polls/tests.py", line 16, in test_was_published_recently_with_future_question
self.assertIs(future_question.was_published_recently(), False)
AssertionError: True is not 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.

Esto es lo que ocurrió:

manage.py test polls looked for tests in the polls application

encontró una subclase de la: clase: clase django.test.TestCase

creó una base de datos especial para las pruebas

buscó métodos de prueba; aquellos cuyos nombres comienzan con test

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

y ejecute la prueba de nuevo:

Creating test database for alias 'default'...


System check identified no issues (0 silenced).
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

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.

Pruebas más exhaustivas


Ya que estamos aquí, podemos además precisar el método was_published_recently(); de hecho, sería verdaderamente vergonzoso si al corregir un bug hubiéramos introducido
otro.

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.

Pruebe una vista


La aplicación encuestas no discrimina en lo absoluto: publicará cualquier pregunta, incluyendo aquellas cuyo campo de pub_date esté en el futuro. Deberíamos actualizar esto.
Establecer un pub_date en el futuro debería signi car que la pregunta se publica en ese momento, pero que será invisible hasta entonces.
Una prueba para una vista
When we xed the bug above, we wrote the test rst and then the code to x it. In fact that was an example of test-driven development, but it doesn’t really matter in which order we do
the work.

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.

El cliente de prueba de Django


Django proporciona una prueba Client para simular un usuario interactúando con el código al nivel de la vista. Podemos utilizarlo en tests.py o incluso en el shell.

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:

/ 

$ python manage.py shell

>>> from django.test.utils import setup_test_environment


>>> setup_test_environment()

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):

>>> from django.test import Client


>>> # create an instance of the client for our use
>>> client = Client()

Con eso listo, podemos pedirle al cliente que haga un trabajo para nosotros:

>>> # get a response from '/'


>>> response = client.get('/')
Not Found: /
>>> # we should expect a 404 from that address; if you instead see an
>>> # "Invalid HTTP_HOST header" error and a 400 response, you probably
>>> # omitted the setup_test_environment() call described earlier.
>>> response.status_code
404
>>> # on the other hand we should expect to find something at '/polls/'
>>> # we'll use 'reverse()' rather than a hardcoded URL
>>> from django.urls import reverse
>>> response = client.get(reverse('polls:index'))
>>> response.status_code
200
>>> response.content
b'\n <ul>\n \n <li><a href="/polls/1/">What&#x27;s up?</a></li>\n \n </ul>\n\n'
>>> response.context['latest_question_list']
<QuerySet [<Question: What's up?>]>

Mejorando nuestra vista


La lista de encuestas muestra las encuestas que aún no están publicadas (es decir, aquellas que tienen una pub_date en el futuro). Vamos a solucionar eso.

En el Tutorial 4 presentamos una vista basada en clases, basada en ListView:


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]

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 

from django.utils import timezone

y luego hay que modi car el método get_queryset como sigue:

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.

Probando nuestra nueva vista


Now you can satisfy yourself that this behaves as expected by ring up runserver, loading the site in your browser, creating Questions with dates in the past and future, and checking
that only those that have been published are listed. You don’t want to have to do that every single time you make any change that might affect this - so let’s also create a test, based on our
shell session above.

Agregue lo siguiente a polls/tests.py:

polls/tests.py 

from django.urls import reverse

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.>']
)

Veamos algunas de estas más de cerca.

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_past_question creamos una pregunta y veri camos que aparezca en la lista.

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)

Ideas para más pruebas


Debemos agregar un método get_queryset similar a ResultsView y crear una nueva clase de pruebas para esa vista. Va a ser muy similar a lo que acabamos de crear; de hecho,
habrá mucha repetición.

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:

Cuando se trata de pruebas, más es mejor


Podría parecer que nuestras pruebas están creciendo fuera de control. A este paso pronto habrá más código en nuestras pruebas que en nuestra aplicación y la repetición es poco
estética en comparación con la re nada concisión del resto de nuestro código.

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:

una TestClass independiente para cada modelo o vista

un método de prueba independiente para cada conjunto de condiciones que usted quiere probar

nombres de los métodos de prueba que describan su función

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.

Las pruebas en Django tiene información completa acerca de las pruebas.

¿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.

Dónde obtener ayuda:

 If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.

Personalice la apariencia de su aplicación


En primer lugar, cree un directorio llamado static en su directorio polls. Django buscará archivos estáticos allí, del mismo modo cómo Django encuentra las plantillas dentro de
polls/templates/.

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.

Espacio de nombres de archivo estático

 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.

Introduzca el siguiente código en esa hoja de estilo (polls/static/polls/style.css):

polls/static/polls/style.css 

li a {
color: green;
}

A continuación, agregue lo siguiente en la parte superior de polls/templates/polls/index.html:

polls/templates/polls/index.html 

{% load static %}

<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}">

La etiqueta de plantilla {% static %} genera la URL absoluta de los archivos estáticos.

That’s all you need to do for development.

Start the server (or restart it if it’s already running):

/ 

$ python manage.py runserver

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.

Luego, agregue a su hoja de estilo (polls/static/polls/style.css):

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.

Dónde obtener ayuda:

 If you’re having trouble going through this tutorial, please head over to the Getting Help section of the FAQ.

Personalice el formulario del sitio administrativo


Al registrar el modelo Question con admin.site.register (Question)`, Django pudo construir una representación del formulario predeterminado. A menudo, usted querrá personalizar el
aspecto y el funcionamiento del formulario del sitio administrativo. Usted hará esto indicándole a Django las opciones que desee cuando registre el objeto.

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 

from django.contrib import admin

from .models import Question

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

from .models import Question

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:

Agregando objetos relacionados


OK, tenemos nuestra página de administración Question, pero una Question tiene varias Choices, y la página de administración no muestra opciones.

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 

from django.contrib import admin

from .models import Choice, Question


# ...
admin.site.register(Choice)

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 

from django.contrib import admin

from .models import Choice, Question

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.»

Cargue la página «Add question» para ver cómo se ve:


Funciona así: Hay tres slots para las opciones relacionadas – como indica extra – y cada vez que usted vuelva a la página «Change» para un objeto ya creado, usted obtiene otros tres
espacios adicionales.

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.

Personalice la lista de cambios del sitio administrativo


Ahora que la página de administración Question se ve bien, vamos a hacer algunos ajustes a la página «change list» – la que muestra todas las preguntas en el sistema.

Así es como se ve en este momento:


Por defecto, Django muestra el str() de cada objeto, pero a veces sería más útil si pudiéramos mostrar los campos individuales. Para hacerlo, utilice la opción del sitio administrativo
:attr::~django.contrib.admin.ModelAdmin.list_display, que es una tupla de nombres de campos para que se muestre como columnas en la página de lista de cambios para el objeto:

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')

Ahora la página de lista de cambios de preguntas se ve así:

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».

Esto se per la bien. Vamos a añadir un poco de capacidad de búsqueda:

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.

Personalice el aspecto del sitio administrativo


Está claro que tener «Django administration» en la parte superior de cada página del sitio administrativo es ridículo. Es sólo texto del marcador de posición.

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.

Personalizando las plantillas de su proyecto


Cree un directorio templates en el directorio de su proyecto (el que contiene manage.py). Las plantillas se pueden ubicar en cualquier parte de su sistema de archivos al que Django
pueda acceder. (Django ejecuta como cualquier usuario ejecuta su servidor.) Sin embargo, una buena práctica a seguir es guardar sus plantillas en el proyecto.

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.

Organizando las plantillas

 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.

¿Dónde están los archivos fuente de Django?

 Si tiene di cultad para encontrar donde están localizados los archivos fuente de Django en su sistema, ejecute el siguiente comando:

/ 

$ python -c "import django; print(django.__path__)"

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.

Personalizando las plantillas de su aplicación


Los lectores agudos preguntarán: ¿Pero si DIRS estaba vacío por defecto, ¿Cómo Django estaba buscando las plantillas del sitio administrativo predeterminado? La respuesta es que, ya
que APP_DIRS <TEMPLATES-APP_DIRS está jado como True, Django busca automáticamente un subdirectorio templates/ dentro de cada paquete de la aplicación, para su uso
como una solución alternativa (no olvide que django.contrib.admin es una aplicación).

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.

Su proyecto y su aplicación reutilizable


Después de los tutoriales anteriores, nuestro proyecto debe tener este aspecto:

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.

Instalación de algunos requisitos previos


El estado actual del empaquetamiento de Python se ha vuelto confuso a causa de varias herramientas. Para este tutorial, vamos a utilizar setuptools para generar nuestro paquete. Es la
herramienta de empaquetamiento recomendada (combinada con el fork distribute). También vamos a utilizar pip para instalar y desinstalarlo. Debe ahora instalar estos dos
paquetes. Si necesita ayuda puede consultar Cómo instalar Django con pip. Del mismo modo, puede instalar el paquete setuptools.

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.

Eligir un nombre para su aplicación

 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.

2. Mueva el directorio polls al directorio django-polls.

3. Cree un archivo django-polls/README.rst con el siguiente contenido:

django-polls/README.rst 

=====
Polls
=====

Polls is a Django app to conduct Web-based polls. For each question,


visitors can choose between a fixed number of answers.

Detailed documentation is in the "docs" directory.

Quick start
-----------

1. Add "polls" to your INSTALLED_APPS setting like this::

INSTALLED_APPS = [
...
'polls',
]

2. Include the polls URLconf in your project urls.py like this::

path('polls/', include('polls.urls')),

3. Run ``python manage.py migrate`` to create the polls models.

4. Start the development server and visit http://127.0.0.1:8000/admin/


to create a poll (you'll need the Admin app enabled).

5. Visit http://127.0.0.1:8000/polls/ to participate in the poll.

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 

from setuptools import setup

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.

Usando su propio paquete


Dado que movimos el directorio polls fuera del proyecto, ya no funciona. Vamos a solucionar esto mediante la instalación de nuestro nuevo paquete django-polls.
Instalando como una librería de usuario

 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).

1. Para instalar el paquete, use pip (ya lo instaló, ¿cierto?):

python -m pip install --user django-polls/dist/django-polls-0.1.tar.gz

2. Con suerte, su proyecto Django ahora debería funcionar de nuevo correctamente. Ejecute el servidor de nuevo para con rmar esto.

3. Para desinstalar el paquete, utilice pip:

python -m pip uninstall django-polls

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:

Enviar por correo electrónico el paquete a un amigo.

Cargar el paquete en su sitio web.

Post the package on a public repository, such as the Python Package Index (PyPI). packaging.python.org has a good tutorial for doing this.

Installing Python packages with a virtual environment


Anteriormente, instalamos la aplicación polls como una librería de usuario. Esto presenta algunas desventajas:

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).

Ahora ¿qué sigue?

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.

O ¡simplemente usted puede echar un vistazo!

Cómo está organizada la documentación


La documentación principal de Django se divide en «trozos» diseñados para atender los diferentes requerimientos:

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.

También se pueden encontrar respuestas a preguntas muy comunes en el FAQ.

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.

Cómo se mejora la documentación


Así como el código base de Django se desarrolla y mejora día a día, nuestra documentación está mejorando constantemente. Mejoramos la documentación por varias razones:

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.

En texto sin formato


Usted puede leer la documentación de Django en texto plano, para su lectura sin conexión a la red o simplemente por comodidad.

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:

/ 

$ grep -r max_length /path/to/django/docs/

Localmente como HTML


You can get a local copy of the HTML documentation following a few steps:

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:

/ 

$ python -m pip install Sphinx

Then, use the included Makefile to turn the documentation into HTML:

$ cd path/to/django/docs
$ make html

Usted tendrá que instalar GNU Make para esto.

Si está en Windows puede utilizar alternativamente el archivo batch incluido:

cd path\to\django\docs
make.bat html

La documentación HTML se ubicará en docs/_build/html.

Diferencias entre versiones


The text documentation in the master branch of the Git repository contains the «latest and greatest» changes and additions. These changes include documentation of new features
targeted for Django’s next feature release. For that reason, it’s worth pointing out our policy to highlight recent changes and additions to Django.

Seguimos esta política:

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.

¿Para quién es este tutorial?

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.

Dónde obtener ayuda:

 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.

¿Qué cubre esta guía?


Te mostraremos cómo contribuir con parches para Django por primera vez. Al nal de este tutorial, contará con un entendimiento básico sobre las herramientas y procesos implicados.
Especí camente, cubriremos lo siguiente:

Instalando Git.

Descargue una copia de la versión de desarrollo de Django

Conjunto de pruebas de funcionamiento de Django.

Escribiendo una prueba para su parche.

Escribiendo el código para su parche.

Probando su parche.

Enviar una solicitud de pull.

Dónde buscar más información.

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.

Para los usuarios de Windows

 See Instale Python on Windows docs for additional guidance.


Código de Conducta
Como un colaborador, usted puede ayudarnos a mantener abierta e inclusiva la comunidad Django. Por favor lea y siga nuestro Código de conducta.

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.

Obtener una copia de la versión de desarrollo de Django


El primer paso para contribuir con Django es obtener una copia del código fuente. Primero, haz un fork a Django en GitHub. Después, desde la línea de comandos, utiliza en comando cd
para navegar hasta el directorio donde querrás que se aloje tu copia local de Django.

Descargue el repositorio de código fuente de Django con el siguiente comando:

/ 

$ git clone https://github.com/YourGitHubName/django.git

Una conexión de ancho de banda bajo?

 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.

Crea un nuevo entorno virtual ejecutando:

/ 

$ python3 -m venv ~/.virtualenvs/djangodev

La ruta es donde se guardará el nuevo entorno en su computadora.

El último paso para con gurar su entorno virtual es activarlo:

$ source ~/.virtualenvs/djangodev/bin/activate

Si el comando source no está disponible, puede intentar usar un punto en su lugar:

$ . ~/.virtualenvs/djangodev/bin/activate

You have to activate the virtual environment whenever you open a new terminal window.

Para los usuarios de Windows

 Para activar su entorno virtual en Windows ejecute:


...\> %HOMEPATH%\.virtualenvs\djangodev\Scripts\activate.bat

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.

Continúa e instala la copia previamente clonada de Django:

/ 

$ python -m pip install -e /path/to/your/local/clone/django/

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.

Creating projects with a local copy of Django


It may be helpful to test your local changes with a Django project. First you have to create a new virtual environment, install the previously cloned local copy of Django in editable mode,
and create a new Django project outside of your local copy of Django. You will immediately see any changes you make to Django in your new project, which is of great help when writing
your rst patch.

Ejecutando el conjunto de pruebas de Django por primera vez


When contributing to Django it’s very important that your code changes don’t introduce bugs into other areas of Django. One way to check that Django still works after you make your
changes is by running Django’s test suite. If all the tests still pass, then you can be reasonably sure that your changes work and haven’t broken other parts of Django. If you’ve never run
Django’s test suite before, it’s a good idea to run it once beforehand to get familiar with its output.

Antes de ejecutar el conjunto de pruebas, instale sus dependencias, primero cambiándo al directorio tests/ de Django y después ejecutando:

/ 

$ python -m pip install -r requirements/py3.txt

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:

Ticket #99999 – Permitir hacer unas tostadas

 Django debe proporcionar una función django.shortcuts.crear_tostadas() que devuelva 'tostadas'.

Bueno, ahora implemente la característica y sus tests asociados.

Crear una rama para su parche


Antes de hacer ningún cambio, cree una nueva rama para el ticket:

/ 

$ git checkout -b ticket_99999

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

Escribiendo algunas pruebas para su reporte


En la mayoría de los casos, para que un parche sea aceptado en Django tiene que incluir pruebas. Para los parches de corrección de bugs, esto signi ca escribir una prueba de regresión
para asegurar que el bug no sea reintroducido en Django más adelante. Una prueba de regresión debe ser escrita de forma tal que falle mientras que todavía exista el bug y pase una vez
que el bug se haya corregido. Para los parches que contienen nuevas características, tendrás que incluir pruebas que garanticen que dichas características estén funcionando
correctamente. Los parches también deben fallar cuando la nueva característica no esté presente y por lo tanto, pasar una vez que haya sido aplicada.

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.

Ahora a nuestro ejemplo práctico.

Escribiendo una prueba para el ticket #99999


Para resolver este ticket, agregaremos una función make_toast() al inicio de del módulo de django. Primero vamos a escribir una prueba que intente usar la función y veri car que su
salida se vea correcta.

Navega a la carpeta tests/shortcuts/ y crea un nuevo chero llamado test_make_toast.py. Añade el siguiente código:

from django.shortcuts import make_toast


from django.test import SimpleTestCase

class MakeToastTests(SimpleTestCase):
def test_make_toast(self):
self.assertEqual(make_toast(), 'toast')

Esta prueba comprueba que la función make_toast() devuelve 'toast'

Pero este asunto de las pruebas parece un poco difícil…

 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.

Ejecutando su nueva prueba


Since we haven’t made any modi cations to django.shortcuts yet, our test should fail. Let’s run all the tests in the shortcuts folder to make sure that’s really what happens. cd to
the Django tests/ directory and run:

/ 

$ ./runtests.py shortcuts

If the tests ran correctly, you should see one failure corresponding to the test method we added, with this error:

ImportError: cannot import name 'make_toast' from 'django.shortcuts'

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.

Escribiendo el código para su ticket


Next we’ll be adding the make_toast() function.

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.

Ejecutando el conjunto de pruebas de Django por segunda vez


Once you’ve veri ed that your patch and your test are working correctly, it’s a good idea to run the entire Django test suite to verify that your change hasn’t introduced any bugs into other
areas of Django. While successfully passing the entire test suite doesn’t guarantee your code is bug free, it does help identify many bugs and regressions that might otherwise go
unnoticed.

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`
~~~~~~~~~~~~~~~~~~~~~~~

* The new :func:`django.shortcuts.make_toast` function returns ``'toast'``.

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á.

Previsualizar sus cambios


Now it’s time to go through all the changes made in our patch. To stage all the changes ready for commit, run:

/ 

$ git add --all

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:

/ 

$ git diff --cached

Use las echas del teclado para moverse arriba y abajo.


diff --git a/django/shortcuts.py b/django/shortcuts.py
index 7ab1df0e9d..8dde9e28d9 100644
--- a/django/shortcuts.py
+++ b/django/shortcuts.py
@@ -156,3 +156,7 @@ def resolve_url(to, *args, **kwargs):

# Finally, fall back and assume it's a URL


return to
+
+
+def make_toast():
+ return 'toast'
diff --git a/docs/releases/2.2.txt b/docs/releases/2.2.txt
index 7d85d30c4a..81518187b3 100644
--- a/docs/releases/2.2.txt
+++ b/docs/releases/2.2.txt
@@ -40,6 +40,11 @@ database constraints. Constraints are added to models using the
Minor features
--------------

+:mod:`django.shortcuts`
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* The new :func:`django.shortcuts.make_toast` function returns ``'toast'``.
+
:mod:`django.contrib.admin`
~~~~~~~~~~~~~~~~~~~~~~~~~~~

diff --git a/docs/topics/http/shortcuts.txt b/docs/topics/http/shortcuts.txt


index 7b3a3a2c00..711bf6bb6d 100644
--- a/docs/topics/http/shortcuts.txt
+++ b/docs/topics/http/shortcuts.txt
@@ -271,3 +271,12 @@ This example is equivalent to::
my_objects = list(MyModel.objects.filter(published=True))
if not my_objects:
raise Http404("No MyModel matches the given query.")
+
+``make_toast()``
+================
+
+.. function:: make_toast()
+
+.. versionadded:: 2.2
+
+Returns ``'toast'``.
diff --git a/tests/shortcuts/test_make_toast.py b/tests/shortcuts/test_make_toast.py
new file mode 100644
index 0000000000..6f4c627b6e
--- /dev/null
+++ b/tests/shortcuts/test_make_toast.py
@@ -0,0 +1,7 @@
+from django.shortcuts import make_toast
+from django.test import SimpleTestCase
+
+
+class MakeToastTests(SimpleTestCase):
+ def test_make_toast(self):
+ self.assertEqual(make_toast(), 'toast')

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.

Consumar los cambios en el parche


Para 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.

Empujar el commit y hacer una solicitud de pull


After committing the patch, send it to your fork on GitHub (substitute «ticket_99999» with the name of your branch if it’s different):

/ 

$ git push origin ticket_99999

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.

Más información para los nuevos colaboradores


Antes de que se involucre mucho en la escritura de parches para Django, hay algo más de información sobre cómo contribuir a la que probablemente debería echarle un vistazo:

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.

Encontrando su primer ticket real


Una vez que haya revisado parte de esa información, estará listo para salir y encontrar un ticket al cual escribirle un parche. Preste especial atención a los tickets con el criterio de «easy
pickings». Estos tickets son a menudo de carácter mucho más simples y son geniales para los que colaboran por primera vez. Una vez que esté familiarizado con como contribuir con
Django, puede pasar a escribir parches para los tickets más difíciles y complicados.

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.

¿Qué hay después de crear una solicitud de pull?


Después de que un ticket tiene un parche, necesita ser revisado por un segundo par de ojos. Después de enviar una solicitud de pull asegúrese de actualizar los metadatos del ticket
mediante el establecimiento de banderas en el ticket para decir «tiene parche», «no necesita pruebas», etc, para que otros puedan encontrarlo para su revisión. Contribuir no
necesariamente siempre signi ca escribir un parche desde cero. Revisar parches existentes es también una contribución muy útil. Consulte: doc:/internals/contributing/triaging-tickets
para más detalles.
FAQ de Django
FAQ: General

¿Por qué existe este proyecto?

¿Qué signi ca «Django» y cómo se pronuncia?

¿Es estable Django?

¿Se puede escalar Django?

¿Quién está detrás de esto?

¿Cómo se licencia Django?

Why does Django include Python’s license le?

¿Qué sitios usan Django?

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?

El <Framework X> tiene la <funcionalidad Y> – ¿por qué Django no?

¿Por qué escribieron todo Django desde cero en vez de usar otras librerías de Python?

¿Django es un Sistema de Gestión de Contenidos (CMS)?

¿Cómo puedo descargar la documentación de Django para leerla sin conexión?

¿Cómo cito a Django?

FAQ: Instalación

¿Cómo comienzo?

¿Cuáles son los requisitos previos de Django?

¿Qué versión de Python puedo usar con Django?

¿Qué versión de Python debería usar con Django?

¿Debería usar la versión estable o la de desarrollo?

FAQ: Usando Django

Why do I get an error about importing DJANGO_SETTINGS_MODULE?

No puedo soportar su lenguaje de plantillas. ¿Tengo que usarlo?

¿Tengo que utilizar su capa del modelo y la capa de base de datos?

¿Cómo uso los campos de imágenes y archivos?

¿Cómo hago que una variable esté disponible para todas mis plantillas?

FAQ: Obteniendo ayuda

¿Cómo hago X cosa?¿Por qué Y no funciona?¿Dónde puedo obtener ayuda?

Why hasn’t my message appeared on django-users?

Nobody answered my question! What should I do?

¡Creo que he hallado un bug! ¿Qué debo hacer?

¡Creo que he hallado un problema de seguridad! ¿Qué debo hacer?

FAQ: Bases de Datos y modelos

¿Cómo puedo ver las consultas SQL plano que Django está ejecutando?

¿Puedo usar Django con una base de datos ya existente?

Si realizo cambios a un modelo, ¿cómo actualizo la base de datos?

¿Los modelos de Django soportan claves primarias en columnas múltiples?

¿Soporta Django bases de datos NoSQL?

¿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?

FAQ: El sitio administrativo

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.

Mi «list_ lter» contiene un ManyToManyField, pero el ltro no se visualiza.

Algunos objetos no están apareciendo en el sitio administrativo.

¿Cómo puedo personalizar la funcionalidad de la interfaz del sitio administrativo?

¡El sitio administrativo generado de forma dinámica se ve feo! ¿Cómo puedo modi carlo?

¿Qué navegadores están soportados para usar el sitio administrativo?

FAQ: Aportando código

¿Cómo puedo empezar a aportar código para Django?

Presenté un parche en el sistema de tickets hace varias semanas. ¿Por qué lo ignoran?

¿Cómo y cuando debo recordarle al equipo sobre un parche que me importa?

¡Pero les he recordado varias veces y siguen ignorando mi parche!

Localización y resolución de problemas

Problemas ejecutando django-admin

Miscelánea
FAQ: General

¿Por qué existe este proyecto?


Django creció de una necesidad muy práctica: World Online, una operación de prensa Web, es responsable de crear aplicaciones Web intensivas en plazos de periodismo. En la sala de
redacción con su ritmo rápido, World Online con frecuencia cuenta solo con horas para llevar una compleja aplicación Web del concepto a su lanzamiento público.

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.

¿Qué signi ca «Django» y cómo se pronuncia?


Django recibe su nombre de Django Reinhardt, un guitarrista de Jazz manouche de 1930’s hasta principios de la década de 1950’s. Hasta hoy en día, es considerado uno de los mejores
guitarristas de todos los tiempos.

Escuche su música. Le va a gustar.

Django se pronuncia YANG-o. Rima con FANG-o. La «D» es muda.

También hemos grabado una muestra de audio de la pronunciación.

¿Es estable Django?


Sí, es bastante estable. Empresas como Disqus, Instagram, Pinterest y Mozilla han estado utilizando Django durante muchos años. Los sitios construidos sobre Django han
experimentado picos de trá co de más de 50 mil visitas por segundo.

¿Se puede escalar Django?


Sí. Comparado con el tiempo de desarrollo, el hardware es barato, por lo que Django está diseñado para tomar ventaja de tanto hardware como le pueda dar.

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é.

¿Quién está detrás de esto?


Django fue desarrollado originalmente en World Online, el departamento web de un periódico en Lawrence, Kansas, EE.UU. Django es dirigido actualmente por un equipo internacional de
voluntarios.

¿Cómo se licencia Django?


Django is distributed under the 3-clause BSD license. This is an open source license granting broad permissions to modify and redistribute Django.

Why does Django include Python’s license le?


Django includes code from the Python standard library. Python is distributed under a permissive open source license. A copy of the Python license is included with Django for compliance
with Python’s terms.

¿Qué sitios usan Django?


DjangoSites.org cuenta con una lista cada vez mayor de sitios web que funcionan con Django.
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?
Bueno, los nombres estándar son debatibles.

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.

El <Framework X> tiene la <funcionalidad Y> – ¿por qué Django no?


Estamos conscientes de que existen otros impresionantes frameworks Web por ahí, y no estamos en contra de tomar prestadas ideas donde sea apropiado. Sin embargo, Django fue
desarrollado precisamente porque no estábamos felices con el estatus quo, así que tenga en cuenta que «porque el <Framework X> la tiene» no va a hacer una razón su ciente para
agregar dicha funcionalidad a Django.

¿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.

En nuestra opinión, ninguno de ellos estaba a la altura de las circunstancias.

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.

Como dijimos: Somos exigentes.

Hemos documentado nuestra losofía en la página de la losofías de diseño.

¿Django es un Sistema de Gestión de Contenidos (CMS)?


No, Django no es un CMS o cualquier tipo de «producto listo para usar». Es un framework para la Web, es una herramienta de programación que le permite crear sitios Web.

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!).

¿Cómo puedo descargar la documentación de Django para leerla sin conexión?


La documentación de Django está disponible en el directorio docs de cada versión tarball de Django. Estos documentos están en formato reST (reStructuredText) y cada archivo de texto
corresponde a una página Web en el sitio o cial de Django.

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.

¿Cómo cito a Django?


Es difícil dar un formato o cial de cita, esto por dos razones: los formatos de cita pueden variar mucho entre publicaciones y los estándares para citar software son aún materia de
debate.

Por ejemplo, estilo APA, dictaría algo como:

Django (Version 1.5) [Computer Software]. (2013). Retrieved from https://djangoproject.com.


Sin embargo, la única guía real es la que su editor aceptará, así que obtenga una de esas guías y llene los vacíos lo mejor que pueda.

Si su guía de estilo de referencias requiere un nombre de editor, use «Django Software Foundation».

Si necesita un lugar de publicación, utilice «Lawrence, Kansas».

Si necesita una dirección web, utilice https://djangoproject.com.

Si necesita un nombre, sólo use «Django» sin ningún eslogan.

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.

2. Instale Django (lea la guía de instalación).

3. Revise el tutorial.

4. Revise el resto de la documentación y haga preguntas si tiene algún problema.

¿Cuáles son los requisitos previos de Django?


Django requires Python. See the table in the next question for the versions of Python that work with each version of Django. Other Python libraries may be required for some use cases,
but you’ll receive an error about them as they’re needed.

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.

¿Qué versión de Python puedo usar con Django?


Versión de Django Versiones de Python
1.11 2.7, 3.4, 3.5, 3.6, 3.7 (añadido el 1.11.17)
2.0 3.4, 3.5, 3.6, 3.7
2.1 3.5, 3.6, 3.7
2.2 3.5, 3.6, 3.7, 3.8 (added in 2.2.8)
3.0, 3.1 3.6, 3.7, 3.8

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.

¿Qué versión de Python debería usar con Django?


Se recomienda usar Python 3. Django 1.11 es la última versión que soporta Python 2.7. El soporte para Python 2.7 en Django 1.11 termina en 2020.

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.

¿Debería usar la versión estable o la de desarrollo?


Generalmente, si está usando código en producción, debería estar usando una versión estable. El proyecto Django publica una versión estable cada nueve meses mas o menos, con
actualizaciones de parches entre estas. Estas versiones estables contienen la API que está cubierta por nuestras garantías de compatibilidad con versiones anteriores; si escribe código
en la versión estable, no debería tener ningún problema actualizándola cuando la siguiente versión o cial sea lanzada.
FAQ: Usando Django

Why do I get an error about importing DJANGO_SETTINGS_MODULE?


Asegúrese de que:

The environment variable DJANGO_SETTINGS_MODULE is set to a fully-quali ed Python module (i.e. «mysite.settings»).

Dicho módulo está en `` sys.path`` (import mysite.settings debería funcionar).

The module doesn’t contain syntax errors.

No puedo soportar su lenguaje de plantillas. ¿Tengo que usarlo?


Nosotros pensamos que nuestro motor de plantillas es la mejor cosa después de la tocineta en trozos, pero reconocemos que escoger un lenguaje de plantillas es algo parecido a una
religión. No hay nada acerca de Django que requiera usar el lenguaje de plantillas, si está apegado a Jinja2, Mako o lo que sea, siéntete libre de usarlos.

¿Tengo que utilizar su capa del modelo y la capa de base de datos?


No. Al igual que el sistema de plantillas, la capa del modelo y la capa de base de datos está separada del resto del framework.

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.

¿Cómo uso los campos de imágenes y archivos?


Utilizar una FileField o una :class:`~django.db.models.ImageField`en un modelo toma unos pocos pasos:

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

¿Cómo hago X cosa?¿Por qué Y no funciona?¿Dónde puedo obtener ayuda?


First, please check if your question is answered on the FAQ. Also, search for answers using your favorite search engine, and in the forum.

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.

Then, please post it in one of the following channels:

The Django Forum section «Using Django». This is for web-based discussions.

The django-users mailing list. This is for email-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.

Why hasn’t my message appeared on django-users?


django-users tiene muchos suscriptores. Esto es bueno para la comunidad ya que signi ca que muchas personas están dispuestas a responder las preguntas. Desafortunadamente,
también quiere decir que django-users es un blanco atractivo para los spammers.

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.

Nobody answered my question! What should I do?


Intente hacer su pregunta más especí ca o proporcione un mejor ejemplo de su problema.

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.

¡Creo que he hallado un bug! ¿Qué debo hacer?


Las instrucciones detalladas sobre cómo tratar un potencial bug se encuentran en nuestra :ref: Guía para contribuir con Django <reporting-bugs>.

¡Creo que he hallado un problema de seguridad! ¿Qué debo hacer?


Si usted piensa que ha encontrado un problema de seguridad con Django, por favor envíe un mensaje a [email protected]. Esta es una lista privada que sólo está accesible
para los desarrolladores de Django altamente con ables y de conocida trayectoria, y sus archivos no pueden ser leídos por el público.

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:

>>> from django.db import connection


>>> connection.queries
[{'sql': 'SELECT polls_polls.id, polls_polls.question, polls_polls.pub_date FROM polls_polls',
'time': '0.002'}]

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:

``sql`` -- The raw SQL statement


``time`` -- How long the statement took to execute, in seconds.

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:

>>> from django.db import connections


>>> connections['my_db_alias'].queries

If you need to clear the query list manually at any point in your functions, call reset_queries(), like this:

from django.db import reset_queries


reset_queries()

¿Puedo usar Django con una base de datos ya existente?


Sí. Consulte Integración con una base de datos heredada.

Si realizo cambios a un modelo, ¿cómo actualizo la base de datos?


Eche un vistazo a la ayuda de Django para migraciones de esquemas.

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.

¿Los modelos de Django soportan claves primarias en columnas múltiples?


No, sólo son soportadas claves primarias de columna única.

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.

¿Soporta Django bases de datos NoSQL?


NoSQL databases are not o cially supported by Django itself. There are, however, a number of side projects and forks which allow NoSQL functionality in Django.

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:

ALTER TABLE myapp_mytable ENGINE=MyISAM;


FAQ: El sitio administrativo

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?».

Mi «list_ lter» contiene un ManyToManyField, pero el ltro no se visualiza.


Django no se molestará en mostrar el ltro para un campo ManyToManyField si hay menos de dos objetos relacionados.

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.

Algunos objetos no están apareciendo en el sitio administrativo.


Un conteo de las inconsistente puede ser causado por la ausencia de valores de una clave externa o un campo de clave externa incorrectamente con gurado como null=False. Si
usted tiene un registro con una ForeignKey apuntando a un objeto inexistente y esa clave externa es incluida en list_display, el registro no será mostrado en la lista del sitio
administrativo porque el modelo de Django declara una restricción de integridad que no está implementada a nivel de la base de datos.

¿Cómo puedo personalizar la funcionalidad de la interfaz del sitio administrativo?


Tiene varias opciones. Si desea trabajar encima de un formulario añadir/cambiar generado automáticamente por Django, puede agregar módulos JavaScript arbitrarios a la página por
medio de la clase Admin del modelo parámetro js. Dicho parámetro es una lista de URLs, en forma de cadenas, que apunta a los módulos de JavaScript que serán incluidos en el
formulario de administración mediante la etiqueta <script>.

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.

¿Qué navegadores están soportados para usar el sitio administrativo?


The admin provides a fully-functional experience to the recent versions of modern, web standards compliant browsers. On desktop this means Chrome, Edge, Firefox, Opera, Safari, and
others.

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

¿Cómo puedo empezar a aportar código para Django?


¡Gracias por preguntar! Hemos redactado un documento entero para esta pregunta. Se titula Contribuyendo con Django.

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.

¿Cómo y cuando debo recordarle al equipo sobre un parche que me importa?


Un mensaje cortés y en buen tiempo a la lista de correo es una manera de obtener atención. Para determinar el momento correcto, tu necesitas estar pendiente del calendario. Si colocas
tu mensaje justo después de una fecha límite de lanzamiento, posiblemente no vas a tener la atención que requieres

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

¡Pero les he recordado varias veces y siguen ignorando mi parche!


En serio, no lo estamos ignorando. Si su parche no tiene la posibilidad de ser incluido en Django, cerraremos el ticket. Para todos los otros tickets, necesitamos priorizar nuestros
esfuerzos lo que signi ca que algunos tickets serán atendidos antes que otros.

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.

Problemas ejecutando django-admin

command not found: django-admin


django-admin should be on your system path if you installed Django via pip. If it’s not in your path, ensure you have your virtual environment activated and you can try running the
equivalent command python -m 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

Estoy obteniendo un UnicodeDecodeError. ¿Qué estoy haciendo mal?


Esta clase de errores ocurre cuando una cadena de bytes que contiene secuencias no ASCII se transforma en una cadena Unicode y la codi cación especi cada es incorrecta. Por lo
general, la salida se ve de la siguiente manera:

UnicodeDecodeError: 'ascii' codec can't decode byte 0x?? in position ?:


ordinal not in range(128)

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

Los modelos almacenan los datos de tu aplicación.

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.

Ve el apunto en las FAQ.

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

Un objeto que representa un conjunto de las a ser extraídas de la base de datos.

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/

el último pedazo (spring) es el slug.

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.

También podría gustarte