Django oficialmente admite las siguientes bases de datos:
También están disponibles varios backends de base de datos proporcionados por terceros.
Django intenta apoyar tantas características como sea posible en todos los backends de base de datos. Sin embargo, no todos los backends de base de datos son iguales, y hemos tenido que tomar decisiones de diseño sobre cuáles características apoyar y qué suposiciones podemos hacer con seguridad.
Este archivo describe algunas de las características que pueden ser relevantes para el uso de Django. No se pretende como reemplazo de la documentación específica del servidor o manuales de referencia.
Las conexiones persistentes evitan el overhead de reestablecer una conexión a la base de datos en cada solicitud HTTP. Se controlan mediante el parámetro CONN_MAX_AGE que define la vida útil máxima de una conexión. Puede establecerse independientemente para cada base de datos.
El valor predeterminado es 0, preservando el comportamiento histórico de cerrar la conexión a la base de datos al final de cada solicitud. Para habilitar conexiones persistentes, establezca CONN_MAX_AGE en un entero positivo de segundos. Para conexiones persistentes ilimitadas, establezca None.
Al utilizar ASGI, las conexiones persistentes deben estar deshabilitadas. En su lugar, utilice la piscina de conexiones integrada de su backend de base de datos si está disponible, o investigue una opción de piscina de conexiones de terceros si es necesario.
Django abre una conexión a la base de datos cuando realiza por primera vez una consulta a la base de datos. Mantiene esta conexión abierta y la reutiliza en solicitudes posteriores. Django cierra la conexión una vez que supera la edad máxima definida por CONN_MAX_AGE o cuando ya no es usable.
En detalle, Django abre automáticamente una conexión a la base de datos cada vez que la necesita y no tiene una ya abierta — ya sea porque se trata de la primera conexión, o porque la conexión anterior fue cerrada.
Al comienzo de cada solicitud, Django cierra la conexión si ha alcanzado su edad máxima. Si tu base de datos termina las conexiones inactivas después de algún tiempo, debes establecer CONN_MAX_AGE en un valor más bajo, para que Django no intente utilizar una conexión que ya ha sido cerrada por el servidor de la base de datos. (Este problema solo puede afectar a sitios con muy baja tráfico.)
Al final de cada solicitud, Django cierra la conexión si ha alcanzado su edad máxima o si se encuentra en un estado de error irreparable. Si han ocurrido errores de base de datos mientras se procesaban las solicitudes, Django verifica si la conexión todavía funciona y la cierra si no lo hace. De esta manera, los errores de base de datos afectan como máximo una solicitud por cada hilo de trabajo del aplicativo; si la conexión se vuelve inutilizable, la siguiente solicitud obtiene una nueva conexión.
Establecer CONN_HEALTH_CHECKS en True puede usarse para mejorar la robustez de la reutilización de conexiones y prevenir errores cuando una conexión ha sido cerrada por el servidor de la base de datos que ahora está listo para aceptar y servir nuevas solicitudes, p. ej., después del reinicio del servidor de la base de datos. El cheque de salud se realiza solo una vez por solicitud y solo si la base de datos se está accediendo durante el manejo de la solicitud.
Dado que cada hilo mantiene su propia conexión, tu base de datos debe admitir al menos tantas conexiones simultáneas como hilos de trabajo tienes.
A veces una base de datos no se accederá por la mayoría de tus vistas, p. ej., porque es la base de datos de un sistema externo, o gracias a la caché. En tales casos, debes establecer CONN_MAX_AGE en un valor bajo o incluso 0, porque no tiene sentido mantener una conexión que es poco probable que se reutilice. Esto ayudará a mantener el número de conexiones simultáneas a esta base de datos pequeño.
El servidor de desarrollo crea un nuevo hilo para cada solicitud que maneja, lo cual anula el efecto de las conexiones persistentes. No habilitarlas durante el desarrollo.
Cuando Django establece una conexión a la base de datos, configura los parámetros adecuados, dependiendo del backend que se esté utilizando. Si habilitas conexiones persistentes, esta configuración ya no se repite cada solicitud. Si modificas parámetros como el nivel de aislamiento o la zona horaria de la conexión, debes restablecer los valores por defecto de Django al final de cada solicitud, forzar un valor apropiado al comienzo de cada solicitud o deshabilitar las conexiones persistentes.
Si se crea una conexión en un proceso de larga duración, fuera del ciclo de solicitud-respuesta de Django, la conexión permanecerá abierta hasta que se cierre explícitamente o ocurra el tiempo de espera. Puedes utilizar django.db.close_old_connections() para cerrar todas las conexiones antiguas o no utilizables.
Django asume que todos los bases de datos usan la codificación UTF-8. Utilizar otras codificaciones puede dar lugar a comportamientos inesperados como errores «valor demasiado largo» desde tu base de datos para datos válidos en Django. Consulta las notas específicas de la base de datos a continuación para obtener información sobre cómo configurar correctamente tu base de datos.
Django admite PostgreSQL 14 y superior. psycopg 3.1.8+ o psycopg2 2.8.4+ es requerido, aunque se recomienda el último psycopg 3.1.8+.
Nota
Es probable que la compatibilidad con psycopg2 sea deprecada y eliminada en algún momento del futuro.
Consulta HOST para obtener más detalles.
Para conectarte utilizando un nombre de servicio desde el archivo de servicios de conexión y una contraseña desde el archivo de contraseñas, debes especificarlos en la parte OPTIONS de tu configuración de base de datos en DATABASES:
settings.py¶DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"OPTIONS": {
"service": "my_service",
"passfile": ".my_pgpass",
},
}
}
.pg_service.conf¶[my_service]
host=localhost
user=USER
dbname=NAME
port=5432
.my_pgpass¶localhost:5432:NAME:USER:PASSWORD
El backend PostgreSQL pasa el contenido de opciones como argumentos clave al constructor de la conexión, lo que permite un control más avanzado del comportamiento del conductor. Todos los parámetros disponibles se describen con detalle en la documentación de PostgreSQL.
Advertencia
No se admite el uso de un nombre de servicio para fines de prueba. Esto puede implementarse más adelante.
Django necesita los siguientes parámetros para sus conexiones a la base de datos:
client_encoding: 'UTF8',
default_transaction_isolation: 'read committed' por defecto, o el valor establecido en las opciones de conexión (consulte más abajo),
Si estos parámetros ya tienen los valores correctos, Django no los establecerá para cada nueva conexión, lo que mejora ligeramente el rendimiento. Puedes configurarlos directamente en postgresql.conf o de manera más conveniente por usuario de base de datos con ALTER ROLE.
Django funcionará correctamente sin esta optimización, pero cada nueva conexión realizará algunas consultas adicionales para establecer estos parámetros.
Al igual que PostgreSQL mismo, Django utiliza por defecto el nivel de aislamiento READ COMMITTED `nivel de aislamiento`_. Si necesita un nivel de aislamiento más alto como REPEATABLE READ o SERIALIZABLE, establezca en la parte OPCIONES de su configuración de base de datos en BASES DE DATOS:
from django.db.backends.postgresql.psycopg_any import IsolationLevel
DATABASES = {
# ...
"OPTIONS": {
"isolation_level": IsolationLevel.SERIALIZABLE,
},
}
Nota
Bajo niveles de aislamiento más altos, su aplicación debe estar preparada para manejar excepciones lanzadas por fallos de serialización. Esta opción está diseñada para usos avanzados.
Si necesita utilizar un rol diferente para las conexiones de base de datos que el rol utilizado para establecer la conexión, establezca en la parte OPCIONES de su configuración de base de datos en BASES DE DATOS:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
# ...
"OPTIONS": {
"assume_role": "my_application_role",
},
},
}
Para utilizar un pool de conexiones con psycopg, puede establecer "pool" en la parte OPCIONES de su configuración de base de datos en BASES DE DATOS para ser un diccionario que se pasa a ConnectionPool, o a True para utilizar los valores por defecto del ConnectionPool:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
# ...
"OPTIONS": {
"pool": True,
},
},
}
Esta es la traducción de los textos:
Con psycopg 3.1.8+, Django utiliza por defecto la vinculación del lado del cliente. Si deseas utilizar la vinculación del lado del servidor configúrala en la parte de opciones de tu configuración de base de datos en DATABASES:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
# ...
"OPTIONS": {
"server_side_binding": True,
},
},
}
Esta opción se ignora con psycopg2.
varchar y text¶Al especificar db_index=True en tus campos del modelo, Django emite normalmente una sola sentencia CREATE INDEX. Sin embargo, si el tipo de base de datos para el campo es varchar o text (por ejemplo, utilizado por CharField, FileField y TextField), entonces Django creará un índice adicional que utiliza una clase de operador apropiada PostgreSQL para la columna. El índice extra es necesario para realizar correctamente las consultas que utilizan el operador LIKE en su SQL, como se hace con los tipos de búsqueda contains y startswith.
Si necesitas agregar una extensión de PostgreSQL (como hstore, postgis, etc.) mediante una migración, utiliza la operación CreateExtension.
Al utilizar QuerySet.iterator(), Django abre un cursor del lado del servidor. Por defecto, PostgreSQL asume que solo se van a recuperar el primer 10% de los resultados de las consultas de cursor. El planificador de consultas pasa menos tiempo planeando la consulta y comienza devolviendo resultados más rápido, pero esto podría disminuir el rendimiento si se recuperan más del 10% de los resultados. Las suposiciones de PostgreSQL sobre el número de filas recuperadas para una consulta de cursor están controladas con la opción cursor_tuple_fraction.
Al utilizar un pooler de conexiones en modo de agrupación de transacciones (por ejemplo, PgBouncer) se requiere deshabilitar los cursor del lado del servidor para esa conexión.
Los cursor del lado del servidor son locales a una conexión y permanecen abiertos al final de una transacción cuando AUTOCOMMIT es True. Una transacción posterior puede intentar obtener más resultados desde un cursor del lado del servidor. En modo de agrupación de transacciones, no hay garantía de que las transacciones posteriores utilicen la misma conexión. Si se utiliza una conexión diferente, se levanta un error cuando la transacción hace referencia al cursor del lado del servidor, porque los cursor del lado del servidor solo están accesibles en la conexión en la cual fueron creados.
Una solución es deshabilitar los cursor del lado del servidor para una conexión en DATABASES estableciendo DISABLE_SERVER_SIDE_CURSORS a True.
Para aprovechar los cursor del lado del servidor en modo de agrupación de transacciones, podrías configurar otra conexión con la base de datos para realizar consultas que utilicen cursor del lado del servidor. Esta conexión necesita ser directa a la base de datos o a un pooler de conexiones en modo de agrupación de sesiones.
Otra opción es envolver cada QuerySet utilizando cursor del lado del servidor dentro de un bloque atomic(), porque deshabilita autocommit durante la duración de la transacción. De esta manera, el cursor del lado del servidor solo vivirá durante la duración de la transacción.
Django utiliza columnas de identidad de PostgreSQL para almacenar claves primarias autoincrementables. Una columna de identidad se poblada con valores desde una secuencia que mantiene el registro del siguiente valor disponible. Asignar manualmente un valor a un campo autoincrementable no actualiza la secuencia del campo, lo que podría causar un conflicto más adelante. Por ejemplo:
>>> from django.contrib.auth.models import User
>>> User.objects.create(username="alice", pk=1)
<User: alice>
>>> # The sequence hasn't been updated; its next value is 1.
>>> User.objects.create(username="bob")
IntegrityError: duplicate key value violates unique constraint
"auth_user_pkey" DETAIL: Key (id)=(1) already exists.
Si necesitas especificar tales valores, resetea la secuencia después para evitar reutilizar un valor que ya está en la tabla. El comando de administración sqlsequencereset genera las sentencias SQL para hacer eso.
Puedes utilizar la configuración de la variable de entorno TEST['TEMPLATE'] para especificar un template (por ejemplo, 'template0') desde el que crear una base de datos de prueba.
Puedes acelerar los tiempos de ejecución de las pruebas configurando PostgreSQL para ser no duradera <https://www.postgresql.org/docs/current/non-durability.html>`_.
Advertencia
Esto es peligroso: hará que tu base de datos sea más susceptible a pérdidas o corrupciones de datos en caso de un fallo del servidor o una pérdida de energía. Solo utiliza esto en una máquina de desarrollo donde puedas restaurar fácilmente el contenido completo de todas las bases de datos del cluster.
Django admite MariaDB 10.5 y versiones posteriores.
Para utilizar MariaDB, utiliza la backend MySQL, que comparte con ella. Consulta las notas de MySQL para obtener más detalles.
Django admite MySQL 8.0.11 y versiones posteriores.
Django utiliza la base de datos information_schema para su característica inspectdb, que contiene información detallada sobre todos los esquemas de bases de datos.
Django espera que la base de datos soporte Unicode (codificación UTF-8) y delega en ella la tarea de enforcing transacciones y integridad referencial. Es importante estar al tanto del hecho de que las dos últimas no se ven realmente impuestas por MySQL cuando se utiliza el motor de almacenamiento MyISAM, consulte la siguiente sección.
MySQL tiene varios motores de almacenamiento. Puedes cambiar el motor de almacenamiento predeterminado en la configuración del servidor.
El motor de almacenamiento por defecto de MySQL es InnoDB. Este motor es completamente transaccional y admite referencias a claves foráneas. Es la elección recomendada. Sin embargo, el contador de autoincremento de InnoDB se pierde al reiniciar MySQL porque no recuerda el valor AUTO_INCREMENT, en su lugar lo recrea como «max(id)+1». Esto puede dar lugar a un uso inadvertido de valores AutoField.
Los principales inconvenientes del MyISAM son que no admite transacciones ni impone restricciones de claves foráneas.
MySQL tiene un par de conectores que implementan la API de bases de datos Python descrita en PEP 249:
mysqlclient es un conector nativo. Es la elección recomendada.
MySQL Connector/Python es un conector puro de Python desde Oracle que no requiere la biblioteca cliente MySQL ni ningún módulo de Python fuera de la biblioteca estándar.
Además de un driver de API de base de datos, Django necesita un adaptador para acceder a los controladores de la base de datos desde su ORM. Django proporciona un adaptador para mysqlclient mientras que MySQL Connector/Python incluye su propio.
Django requiere mysqlclient 1.4.3 o posterior.
MySQL Connector/Python está disponible en la página de descarga. El adaptador de Django está disponible en versiones 1.1.X y posteriores. Es posible que no soporte las últimas versiones de Django.
Si planeas utilizar el soporte a zonas horarias de Django (:doc:`timezone support), utiliza mysql_tzinfo_to_sql para cargar las tablas de zonas horarias en la base de datos MySQL. Esto debe hacerse solo una vez por servidor MySQL, no por base de datos.
Puedes crear tu base de datos utilizando herramientas de línea de comandos y esta SQL:
CREATE DATABASE <dbname> CHARACTER SET utf8mb4;
Esto garantiza que todas las tablas y columnas utilizarán UTF-8 por defecto.
La configuración de collación para una columna controla el orden en que se ordenan los datos, así como qué cadenas se consideran iguales. Puedes especificar el parámetro db_collation para establecer el nombre de la collación de la columna para CharField y TextField.
La collación también se puede configurar a nivel de base de datos y por tabla. Esto está documentado exhaustivamente en la documentación de MySQL. En tales casos, debes establecer la collación directamente manipulando los ajustes o tablas de la base de datos. Django no proporciona una API para cambiarlos.
Por defecto, con una base de datos UTF-8, MySQL utilizará la collación utf8mb4_0900_ai_ci. Esto resulta en todas las comparaciones de igualdad entre cadenas realizadas de manera insensible a mayúsculas y minúsculas. Es decir, "Fred" y "freD" se consideran iguales a nivel de base de datos. Si tienes una restricción única sobre un campo, sería ilegal intentar insertar tanto "aa" como "AA" en la misma columna, ya que comparan como iguales (y, por lo tanto, no únicos) con la collación predeterminada. Si deseas comparaciones sensibles a mayúsculas y minúsculas en una columna o tabla específica, cambia la columna o tabla para utilizar la collación utf8mb4_0900_as_cs.
Ten en cuenta que según Caracteres Unicode de MySQL, las comparaciones para la collación utf8mb4_general_ci son más rápidas, pero ligeramente menos precisas, que las comparaciones para utf8mb4_unicode_ci. Si esto es aceptable para tu aplicación, debes utilizar utf8mb4_general_ci porque es más rápido. Si no lo es (por ejemplo, si requieres el orden de diccionario alemán), utiliza utf8mb4_unicode_ci porque es más preciso.
Advertencia
Los formularios de modelos validan campos únicos en una manera sensible a mayúsculas y minúsculas. Por lo tanto, cuando se utiliza una collación insensible a mayúsculas y minúsculas, un formulario con valores de campo único que difieren solo por mayúsculas y minúsculas pasarán la validación, pero al llamar a save(), se levantará un IntegrityError.
Consulta la documentación sobre configuración de ajustes.
Los ajustes de conexión se utilizan en este orden:
En otras palabras, si estableces el nombre de la base de datos en OPCIONES, esto tendrá prioridad sobre NOMBRE, que sobrescribiría cualquier cosa en un archivo de opción de MySQL.
Aquí tienes una configuración de ejemplo que utiliza un archivo de opciones de MySQL:
# settings.py
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"OPTIONS": {
"read_default_file": "/path/to/my.cnf",
},
}
}
# my.cnf
[client]
database = NAME
user = USER
password = PASSWORD
default-character-set = utf8mb4
Otros varias opciones de conexión MySQLdb pueden ser útiles, como ssl, init_command y sql_mode.
sql_mode¶El valor predeterminado de la opción sql_mode contiene STRICT_TRANS_TABLES. Esa opción convierte las advertencias en errores cuando se trunca la información al insertarla, por lo que Django recomienda encarecidamente activar un modo estricto para MySQL para prevenir pérdidas de datos (ya sea STRICT_TRANS_TABLES o STRICT_ALL_TABLES).
Si necesitas personalizar el modo SQL, puedes establecer la variable sql_mode como otras opciones de MySQL: ya sea en un archivo de configuración o con la entrada 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'" en la parte OPCIONES de tu configuración de base de datos en BASE DE DATOS.
Al ejecutar cargas concurrentes, las transacciones de la base de datos desde diferentes sesiones (digamos, hilos separados que manejan solicitudes distintas) pueden interactuar entre sí. Estas interacciones se ven afectadas por el nivel de aislamiento de transacción de cada sesión. Puedes establecer el nivel de aislamiento de una conexión con una entrada 'isolation_level' en la parte OPCIONES de tu configuración de base de datos en BASE DE DATOS. Los valores válidos para esta entrada son los cuatro niveles de aislamiento estándar:
``”lectura no comprometida””
“lectura comprometida”
“repetible lectura”
“serializable”
o None para utilizar el nivel de aislamiento configurado por el servidor. Sin embargo, Django funciona mejor con y utiliza como defecto la lectura comprometida en lugar del default de MySQL, repetible lectura. La pérdida de datos es posible con repetible lectura. En particular, puede ver casos donde get_or_create() levantará un error de integridad (IntegrityError) pero el objeto no aparecerá en una llamada posterior a get().
Cuando Django genera la esquema, no especifica un motor de almacenamiento, por lo que las tablas se crearán con el motor de almacenamiento predeterminado configurado en su servidor de base de datos. La solución más fácil es configurar el motor de almacenamiento predeterminado de su servidor de base de datos para el motor deseado.
Si está utilizando un servicio de alojamiento y no puede cambiar el motor de almacenamiento predeterminado de su servidor, tiene una o dos opciones.
Después de crear las tablas, ejecute una sentencia ALTER TABLE para convertir una tabla a un nuevo motor de almacenamiento (como InnoDB):
ALTER TABLE <tablename> ENGINE=INNODB;
Esto puede ser tedioso si tiene muchas tablas.
Otra opción es utilizar la opción init_command para MySQLdb antes de crear sus tablas:
"OPTIONS": {
"init_command": "SET default_storage_engine=INNODB",
}
Esto establece el motor de almacenamiento por defecto al conectar a la base de datos. Después de que se hayan creado tus tablas, debes eliminar esta opción ya que agrega una consulta que solo es necesaria durante la creación de las tablas a cada conexión a la base de datos.
Hay problemas conocidos en incluso las últimas versiones de MySQL que pueden causar el cambio del caso de un nombre de tabla cuando ciertas sentencias SQL se ejecutan bajo ciertas condiciones. Se recomienda utilizar nombres de tabla en minúsculas, si es posible, para evitar cualquier problema que pueda surgir debido a este comportamiento. Django utiliza nombres de tabla en minúsculas cuando auto-genera los nombres de tabla desde modelos, por lo que esta es principalmente una consideración si estás sobreescribiendo el nombre de la tabla mediante el parámetro db_table.
Ambos el ORM de Django y MySQL (cuando se utiliza el motor de almacenamiento InnoDB:ref:<mysql-storage-engines> ) admiten puntos de salvaguardia en la base de datos.
Si utilizas el motor de almacenamiento MyISAM ten en cuenta que recibirás errores generados por la base de datos si intentas utilizar los métodos relacionados con los puntos de salvaguardia de la API de transacciones:ref:<topics-db-transactions-savepoints>. La razón para esto es que detectar el motor de almacenamiento de una base de datos o tabla de MySQL es una operación costosa, por lo que se decidió no valer la pena convertir dinámicamente estos métodos en no-op’s basados en los resultados de dicha detección.
Cualquier campo que se almacene con tipos de columna VARCHAR puede tener su max_length restringido a 255 caracteres si estás utilizando unique=True para el campo. Esto afecta a CharField, SlugField. Consulta la documentación de MySQL para obtener más detalles.
TextField¶MySQL puede indexar solo las primeras N caracteres de una columna BLOB o TEXT. Dado que la clase TextField no tiene una longitud definida, no puedes marcarla como unique=True. MySQL reportará: «La columna BLOB/TEXT “<db_column>” se utiliza en la especificación de clave sin incluir una longitud de clave».
MySQL puede almacenar segundos fraccionarios, siempre que la definición de la columna incluya una indicación fraccionaria (por ejemplo DATETIME(6)).
Django no actualizará las columnas existentes para incluir segundos fraccionarios si el servidor de bases de datos lo soporta. Si deseas habilitarlos en una base de datos existente, es responsabilidad tuya actualizar manualmente la columna en la base de datos objetivo ejecutando un comando como:
ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)
o utilizando una operación RunSQL en una migración de datos:ref:data-migrations.
TIMESTAMP¶Si estás utilizando una base de datos legada que contiene columnas TIMESTAMP, debes establecer USE_TZ = False para evitar la corrupción de datos. inspectdb mapea estas columnas a DateTimeField y si habilitas el soporte de zona horaria, tanto MySQL como Django intentarán convertir los valores desde UTC al tiempo local.
QuerySet.select_for_update()¶MySQL y MariaDB no admiten algunas opciones para la sentencia SELECT ... FOR UPDATE. Si se utiliza select_for_update() con una opción no admitida, entonces se levanta un NotSupportedError.
Opción |
MariaDB |
MySQL |
|---|---|---|
|
(X ≥10.6) |
X |
|
X |
X |
|
X |
|
|
Cuando se utiliza select_for_update() en MySQL, asegúrese de filtrar un conjunto de consultas contra al menos un conjunto de campos contenidos en restricciones únicas o solo contra campos cubiertos por índices. De lo contrario, se adquirirá un bloqueo de escritura exclusiva sobre la tabla completa durante la duración de la transacción.
Cuando se realiza una consulta en un tipo de cadena, pero con un valor entero, MySQL convertirá los tipos de todos los valores en la tabla a un entero antes de realizar la comparación. Si su tabla contiene los valores 'abc', 'def' y consulta por WHERE mycolumn=0, ambas filas coincidirán. De manera similar, WHERE mycolumn=1 coincidirá con el valor 'abc1'. Por lo tanto, los campos de tipo cadena incluidos en Django siempre convertirán el valor a una cadena antes de utilizarlo en una consulta.
Si implementa campos de modelo personalizados que heredan directamente de Field, están sobrescribiendo get_prep_value() o utilizan RawSQL, extra() o raw(), debe asegurarse de realizar la tipificación adecuada.
Django admite SQLite 3.31.0 y versiones posteriores.
SQLite proporciona una excelente alternativa de desarrollo para aplicaciones que son predominantemente de solo lectura o requieren un pie de instalación más pequeño. Al igual que todos los servidores de bases de datos, aunque, hay algunas diferencias específicas de SQLite de las cuales debes ser consciente.
Para todas las versiones de SQLite, existe un comportamiento ligeramente contraintuitivo cuando se intenta coincidir con algunos tipos de cadenas. Estos se desencadenan cuando se utilizan los filtros iexact o contains en conjuntos de consultas. El comportamiento se divide en dos casos:
Para la búsqueda de subcadenas, todos los coincidencias se realizan de manera no sensible a mayúsculas y minúsculas. Es decir, un filtro como filter(name__contains=»aa») coincidiría con un nombre de «Aabb».
2. For strings containing characters outside the ASCII range, all exact string
matches are performed case-sensitively, even when the case-insensitive options
are passed into the query. So the iexact filter will behave exactly
the same as the exact filter in these cases.
Algunas posibles soluciones para este problema están documentadas en sqlite.org, pero no se utilizan por el backend de SQLite predeterminado en Django, ya que incorporarlas sería bastante difícil de hacer robustamente. Por lo tanto, Django expone el comportamiento de SQLite por defecto y debes estar al tanto de esto cuando hagas filtrado caso-insensible o de substring.
SQLite no tiene un tipo interno de decimal real. Los valores decimales se convierten internamente al tipo de datos REAL (número en punto flotante IEEE de 8 bytes), como se explica en la documentación de tipos de datos SQLite, por lo que no admiten aritmética de punto flotante decimal redondeada correctamente.
SQLite está diseñado para ser una base de datos ligera y por lo tanto no puede soportar un alto nivel de concurrencia. Los errores OperationalError: database is locked indican que tu aplicación está experimentando más concurrencia de la que sqlite puede manejar en la configuración predeterminada. Este error significa que un hilo o proceso tiene un bloqueo exclusivo sobre la conexión a la base de datos y otro hilo ha agotado el tiempo esperando a que se libere el bloqueo.
La capa de SQLite de Python tiene un valor de tiempo límite predeterminado que determina cuánto tiempo está permitido que el segundo hilo espere en el bloqueo antes de que expire y levante el error OperationalError: database is locked.
Si estás obteniendo este error, puedes resolverlo de la siguiente manera:
Cambiar a otro backend de base de datos. En un punto determinado SQLite se vuelve demasiado «ligero» para aplicaciones del mundo real y estos errores de concurrencia indican que has llegado a ese punto.
Reescribir tu código para reducir la concurrencia y asegurarte de que las transacciones en la base de datos sean cortas.
Aumentar el valor de tiempo límite predeterminado estableciendo la opción de base de datos timeout:
"OPTIONS": {
# ...
"timeout": 20,
# ...
}
Esto hará que SQLite espere un poco más antes de lanzar errores «base de datos bloqueada»; no hará nada para resolverlos.
SQLite admite tres modos de transacción: DEFERRED, IMMEDIATE y EXCLUSIVE.
El modo predeterminado es DEFERRED. Si necesitas usar un modo diferente, configúralo en la parte OPTIONS de tu configuración de base de datos en DATABASES, por ejemplo:
"OPTIONS": {
# ...
"transaction_mode": "IMMEDIATE",
# ...
}
Para asegurarte de que tus transacciones esperen hasta timeout antes de levantar «Base de datos bloqueada», cambia el modo de transacción a INMEDIATO.
Para obtener la mejor rendimiento con INMEDIATO y EXCLUSIVO, las transacciones deben ser lo más cortas posible. Esto puede ser difícil de garantizar para todas tus vistas, por lo que se desaconseja el uso de SOLICITUDES ATÓMICAS en este caso.
Para obtener más información, consulta Transacciones en SQLite.
QuerySet.select_for_update() no soportado¶SQLite no admite la sintaxis SELECT ... FOR UPDATE. Llamar a ella tendrá ningún efecto.
QuerySet.iterator()¶Hay consideraciones especiales descritas en Aislamiento en SQLite cuando se modifica una tabla mientras se itera sobre ella utilizando QuerySet.iterator(). Si se agrega, cambia o elimina una fila dentro del bucle, entonces esa fila puede aparecer o no, o incluso aparecer dos veces, en los resultados posteriores obtenidos desde el iterador. Tu código debe manejar esto.
Para utilizar JSONField en SQLite, debes habilitar la extensión JSON1 en la biblioteca de Python sqlite3. Si no se ha habilitado la extensión en tu instalación, se levantará un error del sistema (fields.E180).
Para habilitar la extensión JSON1 puedes seguir las instrucciones en la página de wiki.
Nota
La extensión JSON1 está habilitada por defecto en SQLite 3.38+.
Las opciones de pragma se pueden configurar al conectar mediante la init_command en la parte OPTIONS de tu configuración de base de datos en DATABASES. El ejemplo a continuación muestra cómo habilitar la durabilidad extra de escrituras sincrónicas y cambiar el cache_size:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
# ...
"OPTIONS": {
"init_command": "PRAGMA synchronous=3; PRAGMA cache_size=2000;",
},
}
}
Django admite versiones 19c o superiores del Servidor de Base de Datos Oracle. Se requiere una versión 2.3.0 o superior del driver Python oracledb.
Obsoleto desde la versión 5.0: El soporte para cx_Oracle está descontinuado.
Para que el comando python manage.py migrate funcione, tu usuario de base de datos Oracle debe tener privilegios para ejecutar los siguientes comandos:
CREATE TABLE
CREATE SEQUENCE
CREATE PROCEDURE
CREAR TRIGGER
Para ejecutar el conjunto de pruebas de un proyecto, el usuario suele necesitar estos privilegios adicionales:
CREAR USUARIO
MODIFICAR USUARIO
ELIMINAR USUARIO
CREAR ESPACIO DE TABLAS
ELIMINAR ESPACIO DE TABLAS
CREAR SESIÓN CON OPCIÓN ADMINISTRATIVA
CREAR TABLA CON OPCIÓN ADMINISTRATIVA
CREAR SECUENCIA CON OPCIÓN ADMINISTRATIVA
CREATE PROCEDURE CON OPCIÓN DE ADMINISTRADOR
CREATE TRIGGER CON OPCIÓN DE ADMINISTRADOR
Mientras que el rol RESOURCE tiene los privilegios requeridos de CREATE TABLE, CREATE SEQUENCE, CREATE PROCEDURE y CREATE TRIGGER, y un usuario con RESOURCE WITH ADMIN OPTION puede otorgar RESOURCE, tal usuario no puede otorgar los privilegios individuales (por ejemplo, CREATE TABLE), y por lo tanto RESOURCE WITH ADMIN OPTION no es usualmente suficiente para ejecutar pruebas.
Algunas suites de pruebas también crean vistas o vistas materializadas; para ejecutar estas, el usuario también necesita los privilegios de CREATE VIEW WITH ADMIN OPTION y CREATE MATERIALIZED VIEW WITH ADMIN OPTION. En particular, esto es necesario para la suite de pruebas propia de Django.
Todos estos privilegios están incluidos en el rol DBA, que es adecuado para su uso en una base de datos privada del desarrollador.
La base de datos Oracle utiliza los paquetes SYS.DBMS_LOB y SYS.DBMS_RANDOM, por lo que tu usuario necesitará permisos de ejecución sobre él. Normalmente es accesible a todos los usuarios por defecto, pero en caso de que no sea así, deberás otorgar permisos como se muestra a continuación:
GRANT EXECUTE ON SYS.DBMS_LOB TO user;
GRANT EXECUTE ON SYS.DBMS_RANDOM TO user;
Para conectarse utilizando el nombre del servicio de tu base de datos Oracle, tu archivo settings.py debería tener algo parecido a esto:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.oracle",
"NAME": "xe",
"USER": "a_user",
"PASSWORD": "a_password",
"HOST": "",
"PORT": "",
}
}
En este caso, debes dejar ambos HOST y PORT vacíos. Sin embargo, si no utilizas un archivo tnsnames.ora o un método de nombre similar y deseas conectarte utilizando el SID («xe» en este ejemplo), entonces rellena ambos HOST y PORT como se muestra a continuación:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.oracle",
"NAME": "xe",
"USER": "a_user",
"PASSWORD": "a_password",
"HOST": "dbprod01ned.mycompany.com",
"PORT": "1540",
}
}
Debes proporcionar tanto HOST como PORT, o dejarlos vacíos. Django utilizará un descriptor de conexión diferente dependiendo de esa elección.
Un DSN completo o una cadena de Easy Connect se puede utilizar en NAME si tanto HOST como PORT están vacíos. Este formato es necesario cuando se utilizan bases de datos RAC o pluggables sin tnsnames.ora, por ejemplo.
Ejemplo de una cadena de Easy Connect:
"NAME": "localhost:1521/orclpdb1"
Ejemplo de un DSN completo:
"NAME": (
"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))"
"(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))"
)
Para utilizar una piscina de conexiones con oracledb, establezca "pool" en True en la parte OPTIONS de su configuración de base de datos. Esto utiliza los valores por defecto del driver create_pool():
DATABASES = {
"default": {
"ENGINE": "django.db.backends.oracle",
# ...
"OPTIONS": {
"pool": True,
},
},
}
Para pasar parámetros personalizados a la función create_pool() del driver, puede establecer alternativamente "pool" como un diccionario:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.oracle",
# ...
"OPTIONS": {
"pool": {
"min": 1,
"max": 10,
# ...
}
},
},
}
Si planea ejecutar Django en un entorno multihilo (por ejemplo, Apache utilizando el módulo MPM por defecto en cualquier sistema operativo moderno), entonces debe establecer la opción threaded de su configuración de base de datos Oracle a True:
"OPTIONS": {
"threaded": True,
}
El fracaso en hacer esto puede resultar en crash y otros comportamientos extraños.
Por defecto, el backend Oracle utiliza una cláusula RETURNING INTO para recuperar eficientemente el valor de un campo AutoField cuando se insertan nuevas filas. Este comportamiento puede resultar en un error de base de datos en ciertos entornos inusuales, como cuando se inserta en una tabla remota o en una vista con un trigger INSTEAD OF. La cláusula RETURNING INTO se puede deshabilitar estableciendo la opción use_returning_into de la configuración de base de datos a False:
"OPTIONS": {
"use_returning_into": False,
}
En este caso, el back-end de Oracle utilizará una consulta SELECT separada para recuperar valores de AutoField.
Oracle impone un límite de longitud en los nombres de 30 caracteres. Para acomodar esto, el back-end trunca los identificadores de la base de datos para que quepan, reemplazando las últimas cuatro caracteres del nombre truncado con un valor hash MD5 repetible. Además, el back-end convierte los identificadores de la base de datos a mayúsculas.
Para evitar estas transformaciones (lo cual es usualmente necesario solo cuando se trabaja con bases de datos legadas o al acceder a tablas que pertenecen a otros usuarios), utilice un nombre entre comillas como valor para db_table:
class LegacyModel(models.Model):
class Meta:
db_table = '"name_left_in_lowercase"'
class ForeignModel(models.Model):
class Meta:
db_table = '"OTHER_USER"."NAME_ONLY_SEEMS_OVER_30"'
Los nombres entre comillas también pueden usarse con los demás back-ends de base de datos soportados por Django; excepto Oracle, sin embargo, las comillas no tienen efecto.
Al ejecutar migrate, se puede encontrar un error ORA-06552 si ciertas palabras clave de Oracle se usan como nombre de campo de modelo o valor de la opción db_column. Django coloca comillas a todos los identificadores utilizados en consultas para prevenir la mayoría de estos problemas, pero este error puede aún ocurrir cuando un tipo de dato de Oracle se usa como nombre de columna. En particular, tenga cuidado al evitar usar los nombres date, timestamp, number o float como nombre de campo.
Django generalmente prefiere utilizar la cadena vacía ('') en lugar de NULL, pero Oracle trata ambos identicamente. Para sortear esto, el back-end de Oracle ignora una opción explícita null en los campos que tienen la cadena vacía como valor posible y genera DDL como si fuera null=True. Cuando se está leyendo desde la base de datos, se asume que un valor NULL en uno de estos campos realmente significa la cadena vacía, y el dato se convierte silenciosamente para reflejar esta suposición.
TextField¶El back-end de Oracle almacena cada campo TextField como una columna NCLOB. Oracle impone algunas limitaciones en el uso general de columnas LOB:
Las columnas LOB no pueden usarse como claves primarias.
Las traducciones son:
Las columnas LOB no pueden usarse en una lista SELECT DISTINCT. Esto significa que intentar usar el método QuerySet.distinct en un modelo que incluye columnas TextField dará como resultado un error ORA-00932 cuando se ejecute contra Oracle. Como solución alternativa, utilice el método QuerySet.defer en conjunto con distinct() para evitar que las columnas TextField sean incluidas en la lista SELECT DISTINCT.
Django viene con backends de bases de datos integrados. Puede heredar un backend existente para modificar su comportamiento, características o configuración.
Por ejemplo, si necesita cambiar una sola característica de la base de datos, primero debe crear un nuevo directorio con un módulo base en él. Por ejemplo:
mysite/
...
mydbengine/
__init__.py
base.py
El módulo base.py debe contener una clase llamada DatabaseWrapper que herede un motor existente del módulo django.db.backends. Aquí hay un ejemplo de cómo heredar el motor PostgreSQL para cambiar la clase de características allows_group_by_selected_pks_on_model:
mysite/mydbengine/base.py¶from django.db.backends.postgresql import base, features
class DatabaseFeatures(features.DatabaseFeatures):
def allows_group_by_selected_pks_on_model(self, model):
return True
class DatabaseWrapper(base.DatabaseWrapper):
features_class = DatabaseFeatures
Finalmente, debe especificar una DATABASE-ENGINE en su archivo settings.py:
DATABASES = {
"default": {
"ENGINE": "mydbengine",
# ...
},
}
Puede ver la lista actual de motores de bases de datos consultando django/db/backends.
Además de las bases de datos oficialmente soportadas, existen backends proporcionados por terceros que te permiten utilizar otras bases de datos con Django:
:CockroachDB <django-cockroachdb>
:microsoft sql server <mssql-django>`
MongoDB <django-mongodb-backend>
Snowflake <django-snowflake>
YugabyteDB <django-yugabytedb>
Las versiones de Django y las características del ORM admitidas por estos backends no oficiales varían considerablemente. Las consultas sobre las capacidades específicas de estos backends no oficiales, junto con cualquier consulta de soporte, deben dirigirse a los canales de soporte proporcionados por cada proyecto de terceros.
may 31, 2026