mirror of
				https://github.com/django/django.git
				synced 2025-10-29 08:36:09 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1133 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1133 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| =========
 | ||
| Databases
 | ||
| =========
 | ||
| 
 | ||
| Django officially supports the following databases:
 | ||
| 
 | ||
| * :ref:`PostgreSQL <postgresql-notes>`
 | ||
| * :ref:`MariaDB <mariadb-notes>`
 | ||
| * :ref:`MySQL <mysql-notes>`
 | ||
| * :ref:`Oracle <oracle-notes>`
 | ||
| * :ref:`SQLite <sqlite-notes>`
 | ||
| 
 | ||
| There are also a number of :ref:`database backends provided by third parties
 | ||
| <third-party-notes>`.
 | ||
| 
 | ||
| Django attempts to support as many features as possible on all database
 | ||
| backends. However, not all database backends are alike, and we've had to make
 | ||
| design decisions on which features to support and which assumptions we can make
 | ||
| safely.
 | ||
| 
 | ||
| This file describes some of the features that might be relevant to Django
 | ||
| usage. It is not intended as a replacement for server-specific documentation or
 | ||
| reference manuals.
 | ||
| 
 | ||
| General notes
 | ||
| =============
 | ||
| 
 | ||
| .. _persistent-database-connections:
 | ||
| 
 | ||
| Persistent connections
 | ||
| ----------------------
 | ||
| 
 | ||
| Persistent connections avoid the overhead of reestablishing a connection to
 | ||
| the database in each request. They're controlled by the
 | ||
| :setting:`CONN_MAX_AGE` parameter which defines the maximum lifetime of a
 | ||
| connection. It can be set independently for each database.
 | ||
| 
 | ||
| The default value is ``0``, preserving the historical behavior of closing the
 | ||
| database connection at the end of each request. To enable persistent
 | ||
| connections, set :setting:`CONN_MAX_AGE` to a positive integer of seconds. For
 | ||
| unlimited persistent connections, set it to ``None``.
 | ||
| 
 | ||
| Connection management
 | ||
| ~~~~~~~~~~~~~~~~~~~~~
 | ||
| 
 | ||
| Django opens a connection to the database when it first makes a database
 | ||
| query. It keeps this connection open and reuses it in subsequent requests.
 | ||
| Django closes the connection once it exceeds the maximum age defined by
 | ||
| :setting:`CONN_MAX_AGE` or when it isn't usable any longer.
 | ||
| 
 | ||
| In detail, Django automatically opens a connection to the database whenever it
 | ||
| needs one and doesn't have one already — either because this is the first
 | ||
| connection, or because the previous connection was closed.
 | ||
| 
 | ||
| At the beginning of each request, Django closes the connection if it has
 | ||
| reached its maximum age. If your database terminates idle connections after
 | ||
| some time, you should set :setting:`CONN_MAX_AGE` to a lower value, so that
 | ||
| Django doesn't attempt to use a connection that has been terminated by the
 | ||
| database server. (This problem may only affect very low traffic sites.)
 | ||
| 
 | ||
| At the end of each request, Django closes the connection if it has reached its
 | ||
| maximum age or if it is in an unrecoverable error state. If any database
 | ||
| errors have occurred while processing the requests, Django checks whether the
 | ||
| connection still works, and closes it if it doesn't. Thus, database errors
 | ||
| affect at most one request per each application's worker thread; if the
 | ||
| connection becomes unusable, the next request gets a fresh connection.
 | ||
| 
 | ||
| Setting :setting:`CONN_HEALTH_CHECKS` to ``True`` can be used to improve the
 | ||
| robustness of connection reuse and prevent errors when a connection has been
 | ||
| closed by the database server which is now ready to accept and serve new
 | ||
| connections, e.g. after database server restart. The health check is performed
 | ||
| only once per request and only if the database is being accessed during the
 | ||
| handling of the request.
 | ||
| 
 | ||
| .. versionchanged:: 4.1
 | ||
| 
 | ||
|     The :setting:`CONN_HEALTH_CHECKS` setting was added.
 | ||
| 
 | ||
| Caveats
 | ||
| ~~~~~~~
 | ||
| 
 | ||
| Since each thread maintains its own connection, your database must support at
 | ||
| least as many simultaneous connections as you have worker threads.
 | ||
| 
 | ||
| Sometimes a database won't be accessed by the majority of your views, for
 | ||
| example because it's the database of an external system, or thanks to caching.
 | ||
| In such cases, you should set :setting:`CONN_MAX_AGE` to a low value or even
 | ||
| ``0``, because it doesn't make sense to maintain a connection that's unlikely
 | ||
| to be reused. This will help keep the number of simultaneous connections to
 | ||
| this database small.
 | ||
| 
 | ||
| The development server creates a new thread for each request it handles,
 | ||
| negating the effect of persistent connections. Don't enable them during
 | ||
| development.
 | ||
| 
 | ||
| When Django establishes a connection to the database, it sets up appropriate
 | ||
| parameters, depending on the backend being used. If you enable persistent
 | ||
| connections, this setup is no longer repeated every request. If you modify
 | ||
| parameters such as the connection's isolation level or time zone, you should
 | ||
| either restore Django's defaults at the end of each request, force an
 | ||
| appropriate value at the beginning of each request, or disable persistent
 | ||
| connections.
 | ||
| 
 | ||
| Encoding
 | ||
| --------
 | ||
| 
 | ||
| Django assumes that all databases use UTF-8 encoding. Using other encodings may
 | ||
| result in unexpected behavior such as "value too long" errors from your
 | ||
| database for data that is valid in Django. See the database specific notes
 | ||
| below for information on how to set up your database correctly.
 | ||
| 
 | ||
| .. _postgresql-notes:
 | ||
| 
 | ||
| PostgreSQL notes
 | ||
| ================
 | ||
| 
 | ||
| Django supports PostgreSQL 12 and higher. `psycopg2`_ 2.8.4 or higher is
 | ||
| required, though the latest release is recommended.
 | ||
| 
 | ||
| .. _psycopg2: https://www.psycopg.org/
 | ||
| 
 | ||
| .. _postgresql-connection-settings:
 | ||
| 
 | ||
| PostgreSQL connection settings
 | ||
| -------------------------------
 | ||
| 
 | ||
| See :setting:`HOST` for details.
 | ||
| 
 | ||
| To connect using a service name from the `connection service file`_ and a
 | ||
| password from the `password file`_, you must specify them in the
 | ||
| :setting:`OPTIONS` part of your database configuration in :setting:`DATABASES`:
 | ||
| 
 | ||
| .. code-block:: python
 | ||
|     :caption: ``settings.py``
 | ||
| 
 | ||
|     DATABASES = {
 | ||
|         'default': {
 | ||
|             'ENGINE': 'django.db.backends.postgresql',
 | ||
|             'OPTIONS': {
 | ||
|                 'service': 'my_service',
 | ||
|                 'passfile': '.my_pgpass',
 | ||
|             },
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
| .. code-block:: text
 | ||
|     :caption: ``.pg_service.conf``
 | ||
| 
 | ||
|     [my_service]
 | ||
|     host=localhost
 | ||
|     user=USER
 | ||
|     dbname=NAME
 | ||
|     port=5432
 | ||
| 
 | ||
| .. code-block:: text
 | ||
|     :caption: ``.my_pgpass``
 | ||
| 
 | ||
|     localhost:5432:NAME:USER:PASSWORD
 | ||
| 
 | ||
| .. _connection service file: https://www.postgresql.org/docs/current/libpq-pgservice.html
 | ||
| .. _password file: https://www.postgresql.org/docs/current/libpq-pgpass.html
 | ||
| 
 | ||
| .. warning::
 | ||
| 
 | ||
|     Using a service name for testing purposes is not supported. This
 | ||
|     :ticket:`may be implemented later <33685>`.
 | ||
| 
 | ||
| Optimizing PostgreSQL's configuration
 | ||
| -------------------------------------
 | ||
| 
 | ||
| Django needs the following parameters for its database connections:
 | ||
| 
 | ||
| - ``client_encoding``: ``'UTF8'``,
 | ||
| - ``default_transaction_isolation``: ``'read committed'`` by default,
 | ||
|   or the value set in the connection options (see below),
 | ||
| - ``timezone``:
 | ||
|     - when :setting:`USE_TZ` is ``True``, ``'UTC'`` by default, or the
 | ||
|       :setting:`TIME_ZONE <DATABASE-TIME_ZONE>` value set for the connection,
 | ||
|     - when :setting:`USE_TZ` is ``False``, the value of the global
 | ||
|       :setting:`TIME_ZONE` setting.
 | ||
| 
 | ||
| If these parameters already have the correct values, Django won't set them for
 | ||
| every new connection, which improves performance slightly. You can configure
 | ||
| them directly in :file:`postgresql.conf` or more conveniently per database
 | ||
| user with `ALTER ROLE`_.
 | ||
| 
 | ||
| Django will work just fine without this optimization, but each new connection
 | ||
| will do some additional queries to set these parameters.
 | ||
| 
 | ||
| .. _ALTER ROLE: https://www.postgresql.org/docs/current/sql-alterrole.html
 | ||
| 
 | ||
| .. _database-isolation-level:
 | ||
| 
 | ||
| Isolation level
 | ||
| ---------------
 | ||
| 
 | ||
| Like PostgreSQL itself, Django defaults to the ``READ COMMITTED`` `isolation
 | ||
| level`_. If you need a higher isolation level such as ``REPEATABLE READ`` or
 | ||
| ``SERIALIZABLE``, set it in the :setting:`OPTIONS` part of your database
 | ||
| configuration in :setting:`DATABASES`::
 | ||
| 
 | ||
|     import psycopg2.extensions
 | ||
| 
 | ||
|     DATABASES = {
 | ||
|         # ...
 | ||
|         'OPTIONS': {
 | ||
|             'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE,
 | ||
|         },
 | ||
|     }
 | ||
| 
 | ||
| .. note::
 | ||
| 
 | ||
|     Under higher isolation levels, your application should be prepared to
 | ||
|     handle exceptions raised on serialization failures. This option is
 | ||
|     designed for advanced uses.
 | ||
| 
 | ||
| .. _isolation level: https://www.postgresql.org/docs/current/transaction-iso.html
 | ||
| 
 | ||
| Indexes for ``varchar`` and ``text`` columns
 | ||
| --------------------------------------------
 | ||
| 
 | ||
| When specifying ``db_index=True`` on your model fields, Django typically
 | ||
| outputs a single ``CREATE INDEX`` statement.  However, if the database type
 | ||
| for the field is either ``varchar`` or ``text`` (e.g., used by ``CharField``,
 | ||
| ``FileField``, and ``TextField``), then Django will create
 | ||
| an additional index that uses an appropriate `PostgreSQL operator class`_
 | ||
| for the column.  The extra index is necessary to correctly perform
 | ||
| lookups that use the ``LIKE`` operator in their SQL, as is done with the
 | ||
| ``contains`` and ``startswith`` lookup types.
 | ||
| 
 | ||
| .. _PostgreSQL operator class: https://www.postgresql.org/docs/current/indexes-opclass.html
 | ||
| 
 | ||
| Migration operation for adding extensions
 | ||
| -----------------------------------------
 | ||
| 
 | ||
| If you need to add a PostgreSQL extension (like ``hstore``, ``postgis``, etc.)
 | ||
| using a migration, use the
 | ||
| :class:`~django.contrib.postgres.operations.CreateExtension` operation.
 | ||
| 
 | ||
| .. _postgresql-server-side-cursors:
 | ||
| 
 | ||
| Server-side cursors
 | ||
| -------------------
 | ||
| 
 | ||
| When using :meth:`QuerySet.iterator()
 | ||
| <django.db.models.query.QuerySet.iterator>`, Django opens a :ref:`server-side
 | ||
| cursor <psycopg2:server-side-cursors>`. By default, PostgreSQL assumes that
 | ||
| only the first 10% of the results of cursor queries will be fetched. The query
 | ||
| planner spends less time planning the query and starts returning results
 | ||
| faster, but this could diminish performance if more than 10% of the results are
 | ||
| retrieved. PostgreSQL's assumptions on the number of rows retrieved for a
 | ||
| cursor query is controlled with the `cursor_tuple_fraction`_ option.
 | ||
| 
 | ||
| .. _cursor_tuple_fraction: https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-CURSOR-TUPLE-FRACTION
 | ||
| 
 | ||
| .. _transaction-pooling-server-side-cursors:
 | ||
| 
 | ||
| Transaction pooling and server-side cursors
 | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | ||
| 
 | ||
| Using a connection pooler in transaction pooling mode (e.g. `PgBouncer`_)
 | ||
| requires disabling server-side cursors for that connection.
 | ||
| 
 | ||
| Server-side cursors are local to a connection and remain open at the end of a
 | ||
| transaction when :setting:`AUTOCOMMIT <DATABASE-AUTOCOMMIT>` is ``True``. A
 | ||
| subsequent transaction may attempt to fetch more results from a server-side
 | ||
| cursor. In transaction pooling mode, there's no guarantee that subsequent
 | ||
| transactions will use the same connection. If a different connection is used,
 | ||
| an error is raised when the transaction references the server-side cursor,
 | ||
| because server-side cursors are only accessible in the connection in which they
 | ||
| were created.
 | ||
| 
 | ||
| One solution is to disable server-side cursors for a connection in
 | ||
| :setting:`DATABASES` by setting :setting:`DISABLE_SERVER_SIDE_CURSORS
 | ||
| <DATABASE-DISABLE_SERVER_SIDE_CURSORS>` to ``True``.
 | ||
| 
 | ||
| To benefit from server-side cursors in transaction pooling mode, you could set
 | ||
| up :doc:`another connection to the database </topics/db/multi-db>` in order to
 | ||
| perform queries that use server-side cursors. This connection needs to either
 | ||
| be directly to the database or to a connection pooler in session pooling mode.
 | ||
| 
 | ||
| Another option is to wrap each ``QuerySet`` using server-side cursors in an
 | ||
| :func:`~django.db.transaction.atomic` block, because it disables ``autocommit``
 | ||
| for the duration of the transaction. This way, the server-side cursor will only
 | ||
| live for the duration of the transaction.
 | ||
| 
 | ||
| .. _PgBouncer: https://www.pgbouncer.org/
 | ||
| 
 | ||
| .. _manually-specified-autoincrement-pk:
 | ||
| 
 | ||
| Manually-specifying values of auto-incrementing primary keys
 | ||
| ------------------------------------------------------------
 | ||
| 
 | ||
| Django uses PostgreSQL's identity columns to store auto-incrementing primary
 | ||
| keys. An identity column is populated with values from a `sequence`_ that keeps
 | ||
| track of the next available value. Manually assigning a value to an
 | ||
| auto-incrementing field doesn't update the field's sequence, which might later
 | ||
| cause a conflict. For example::
 | ||
| 
 | ||
|     >>> 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.
 | ||
| 
 | ||
| If you need to specify such values, reset the sequence afterward to avoid
 | ||
| reusing a value that's already in the table. The :djadmin:`sqlsequencereset`
 | ||
| management command generates the SQL statements to do that.
 | ||
| 
 | ||
| .. versionchanged:: 4.1
 | ||
| 
 | ||
|     In older versions, PostgreSQL’s ``SERIAL`` data type was used instead of
 | ||
|     identity columns.
 | ||
| 
 | ||
| .. _sequence: https://www.postgresql.org/docs/current/sql-createsequence.html
 | ||
| 
 | ||
| Test database templates
 | ||
| -----------------------
 | ||
| 
 | ||
| You can use the :setting:`TEST['TEMPLATE'] <TEST_TEMPLATE>` setting to specify
 | ||
| a `template`_ (e.g. ``'template0'``) from which to create a test database.
 | ||
| 
 | ||
| .. _template: https://www.postgresql.org/docs/current/sql-createdatabase.html
 | ||
| 
 | ||
| Speeding up test execution with non-durable settings
 | ||
| ----------------------------------------------------
 | ||
| 
 | ||
| You can speed up test execution times by `configuring PostgreSQL to be
 | ||
| non-durable <https://www.postgresql.org/docs/current/non-durability.html>`_.
 | ||
| 
 | ||
| .. warning::
 | ||
| 
 | ||
|     This is dangerous: it will make your database more susceptible to data loss
 | ||
|     or corruption in the case of a server crash or power loss. Only use this on
 | ||
|     a development machine where you can easily restore the entire contents of
 | ||
|     all databases in the cluster.
 | ||
| 
 | ||
| .. _mariadb-notes:
 | ||
| 
 | ||
| MariaDB notes
 | ||
| =============
 | ||
| 
 | ||
| Django supports MariaDB 10.4 and higher.
 | ||
| 
 | ||
| To use MariaDB, use the MySQL backend, which is shared between the two. See the
 | ||
| :ref:`MySQL notes <mysql-notes>` for more details.
 | ||
| 
 | ||
| .. _mysql-notes:
 | ||
| 
 | ||
| MySQL notes
 | ||
| ===========
 | ||
| 
 | ||
| Version support
 | ||
| ---------------
 | ||
| 
 | ||
| Django supports MySQL 8 and higher.
 | ||
| 
 | ||
| Django's ``inspectdb`` feature uses the ``information_schema`` database, which
 | ||
| contains detailed data on all database schemas.
 | ||
| 
 | ||
| Django expects the database to support Unicode (UTF-8 encoding) and delegates to
 | ||
| it the task of enforcing transactions and referential integrity. It is important
 | ||
| to be aware of the fact that the two latter ones aren't actually enforced by
 | ||
| MySQL when using the MyISAM storage engine, see the next section.
 | ||
| 
 | ||
| .. _mysql-storage-engines:
 | ||
| 
 | ||
| Storage engines
 | ||
| ---------------
 | ||
| 
 | ||
| MySQL has several `storage engines`_. You can change the default storage engine
 | ||
| in the server configuration.
 | ||
| 
 | ||
| MySQL's default storage engine is InnoDB_. This engine is fully transactional
 | ||
| and supports foreign key references. It's the recommended choice. However, the
 | ||
| InnoDB autoincrement counter is lost on a MySQL restart because it does not
 | ||
| remember the ``AUTO_INCREMENT`` value, instead recreating it as "max(id)+1".
 | ||
| This may result in an inadvertent reuse of :class:`~django.db.models.AutoField`
 | ||
| values.
 | ||
| 
 | ||
| The main drawbacks of MyISAM_ are that it doesn't support transactions or
 | ||
| enforce foreign-key constraints.
 | ||
| 
 | ||
| .. _storage engines: https://dev.mysql.com/doc/refman/en/storage-engines.html
 | ||
| .. _MyISAM: https://dev.mysql.com/doc/refman/en/myisam-storage-engine.html
 | ||
| .. _InnoDB: https://dev.mysql.com/doc/refman/en/innodb-storage-engine.html
 | ||
| 
 | ||
| .. _mysql-db-api-drivers:
 | ||
| 
 | ||
| MySQL DB API Drivers
 | ||
| --------------------
 | ||
| 
 | ||
| MySQL has a couple drivers that implement the Python Database API described in
 | ||
| :pep:`249`:
 | ||
| 
 | ||
| - `mysqlclient`_ is a native driver. It's **the recommended choice**.
 | ||
| - `MySQL Connector/Python`_ is a pure Python driver from Oracle that does not
 | ||
|   require the MySQL client library or any Python modules outside the standard
 | ||
|   library.
 | ||
| 
 | ||
| .. _mysqlclient: https://pypi.org/project/mysqlclient/
 | ||
| .. _MySQL Connector/Python: https://dev.mysql.com/downloads/connector/python/
 | ||
| 
 | ||
| These drivers are thread-safe and provide connection pooling.
 | ||
| 
 | ||
| In addition to a DB API driver, Django needs an adapter to access the database
 | ||
| drivers from its ORM. Django provides an adapter for mysqlclient while MySQL
 | ||
| Connector/Python includes `its own`_.
 | ||
| 
 | ||
| .. _its own: https://dev.mysql.com/doc/connector-python/en/connector-python-django-backend.html
 | ||
| 
 | ||
| mysqlclient
 | ||
| ~~~~~~~~~~~
 | ||
| 
 | ||
| Django requires `mysqlclient`_ 1.4.0 or later.
 | ||
| 
 | ||
| MySQL Connector/Python
 | ||
| ~~~~~~~~~~~~~~~~~~~~~~
 | ||
| 
 | ||
| MySQL Connector/Python is available from the `download page`_.
 | ||
| The Django adapter is available in versions 1.1.X and later. It may not
 | ||
| support the most recent releases of Django.
 | ||
| 
 | ||
| .. _download page: https://dev.mysql.com/downloads/connector/python/
 | ||
| 
 | ||
| .. _mysql-time-zone-definitions:
 | ||
| 
 | ||
| Time zone definitions
 | ||
| ---------------------
 | ||
| 
 | ||
| If you plan on using Django's :doc:`timezone support </topics/i18n/timezones>`,
 | ||
| use `mysql_tzinfo_to_sql`_ to load time zone tables into the MySQL database.
 | ||
| This needs to be done just once for your MySQL server, not per database.
 | ||
| 
 | ||
| .. _mysql_tzinfo_to_sql: https://dev.mysql.com/doc/refman/en/mysql-tzinfo-to-sql.html
 | ||
| 
 | ||
| Creating your database
 | ||
| ----------------------
 | ||
| 
 | ||
| You can `create your database`_ using the command-line tools and this SQL::
 | ||
| 
 | ||
|   CREATE DATABASE <dbname> CHARACTER SET utf8;
 | ||
| 
 | ||
| This ensures all tables and columns will use UTF-8 by default.
 | ||
| 
 | ||
| .. _create your database: https://dev.mysql.com/doc/refman/en/create-database.html
 | ||
| 
 | ||
| .. _mysql-collation:
 | ||
| 
 | ||
| Collation settings
 | ||
| ~~~~~~~~~~~~~~~~~~
 | ||
| 
 | ||
| The collation setting for a column controls the order in which data is sorted
 | ||
| as well as what strings compare as equal. You can specify the ``db_collation``
 | ||
| parameter to set the collation name of the column for
 | ||
| :attr:`CharField <django.db.models.CharField.db_collation>` and
 | ||
| :attr:`TextField <django.db.models.TextField.db_collation>`.
 | ||
| 
 | ||
| The collation can also be set on a database-wide level and per-table. This is
 | ||
| `documented thoroughly`_ in the MySQL documentation. In such cases, you must
 | ||
| set the collation by directly manipulating the database settings or tables.
 | ||
| Django doesn't provide an API to change them.
 | ||
| 
 | ||
| .. _documented thoroughly: https://dev.mysql.com/doc/refman/en/charset.html
 | ||
| 
 | ||
| By default, with a UTF-8 database, MySQL will use the
 | ||
| ``utf8_general_ci`` collation. This results in all string equality
 | ||
| comparisons being done in a *case-insensitive* manner. That is, ``"Fred"`` and
 | ||
| ``"freD"`` are considered equal at the database level. If you have a unique
 | ||
| constraint on a field, it would be illegal to try to insert both ``"aa"`` and
 | ||
| ``"AA"`` into the same column, since they compare as equal (and, hence,
 | ||
| non-unique) with the default collation. If you want case-sensitive comparisons
 | ||
| on a particular column or table, change the column or table to use the
 | ||
| ``utf8_bin`` collation.
 | ||
| 
 | ||
| Please note that according to `MySQL Unicode Character Sets`_, comparisons for
 | ||
| the ``utf8_general_ci`` collation are faster, but slightly less correct, than
 | ||
| comparisons for ``utf8_unicode_ci``. If this is acceptable for your application,
 | ||
| you should use ``utf8_general_ci`` because it is faster. If this is not acceptable
 | ||
| (for example, if you require German dictionary order), use ``utf8_unicode_ci``
 | ||
| because it is more accurate.
 | ||
| 
 | ||
| .. _MySQL Unicode Character Sets: https://dev.mysql.com/doc/refman/en/charset-unicode-sets.html
 | ||
| 
 | ||
| .. warning::
 | ||
| 
 | ||
|     Model formsets validate unique fields in a case-sensitive manner. Thus when
 | ||
|     using a case-insensitive collation, a formset with unique field values that
 | ||
|     differ only by case will pass validation, but upon calling ``save()``, an
 | ||
|     ``IntegrityError`` will be raised.
 | ||
| 
 | ||
| Connecting to the database
 | ||
| --------------------------
 | ||
| 
 | ||
| Refer to the :doc:`settings documentation </ref/settings>`.
 | ||
| 
 | ||
| Connection settings are used in this order:
 | ||
| 
 | ||
| #. :setting:`OPTIONS`.
 | ||
| #. :setting:`NAME`, :setting:`USER`, :setting:`PASSWORD`, :setting:`HOST`,
 | ||
|    :setting:`PORT`
 | ||
| #. MySQL option files.
 | ||
| 
 | ||
| In other words, if you set the name of the database in :setting:`OPTIONS`,
 | ||
| this will take precedence over :setting:`NAME`, which would override
 | ||
| anything in a `MySQL option file`_.
 | ||
| 
 | ||
| Here's a sample configuration which uses a MySQL option file::
 | ||
| 
 | ||
|     # 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 = utf8
 | ||
| 
 | ||
| Several other `MySQLdb connection options`_ may be useful, such as ``ssl``,
 | ||
| ``init_command``, and ``sql_mode``.
 | ||
| 
 | ||
| .. _MySQL option file: https://dev.mysql.com/doc/refman/en/option-files.html
 | ||
| .. _MySQLdb connection options: https://mysqlclient.readthedocs.io/user_guide.html#functions-and-attributes
 | ||
| 
 | ||
| .. _mysql-sql-mode:
 | ||
| 
 | ||
| Setting ``sql_mode``
 | ||
| ~~~~~~~~~~~~~~~~~~~~
 | ||
| 
 | ||
| The default value of the ``sql_mode`` option contains ``STRICT_TRANS_TABLES``.
 | ||
| That option escalates warnings into errors when data are truncated upon
 | ||
| insertion, so Django highly recommends activating a `strict mode`_ for MySQL to
 | ||
| prevent data loss (either ``STRICT_TRANS_TABLES`` or ``STRICT_ALL_TABLES``).
 | ||
| 
 | ||
| .. _strict mode: https://dev.mysql.com/doc/refman/en/sql-mode.html#sql-mode-strict
 | ||
| 
 | ||
| If you need to customize the SQL mode, you can set the ``sql_mode`` variable
 | ||
| like other MySQL options: either in a config file or with the entry
 | ||
| ``'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"`` in the
 | ||
| :setting:`OPTIONS` part of your database configuration in :setting:`DATABASES`.
 | ||
| 
 | ||
| .. _mysql-isolation-level:
 | ||
| 
 | ||
| Isolation level
 | ||
| ~~~~~~~~~~~~~~~
 | ||
| 
 | ||
| When running concurrent loads, database transactions from different sessions
 | ||
| (say, separate threads handling different requests) may interact with each
 | ||
| other. These interactions are affected by each session's `transaction isolation
 | ||
| level`_. You can set a connection's isolation level with an
 | ||
| ``'isolation_level'`` entry in the :setting:`OPTIONS` part of your database
 | ||
| configuration in :setting:`DATABASES`. Valid values for
 | ||
| this entry are the four standard isolation levels:
 | ||
| 
 | ||
| * ``'read uncommitted'``
 | ||
| * ``'read committed'``
 | ||
| * ``'repeatable read'``
 | ||
| * ``'serializable'``
 | ||
| 
 | ||
| or ``None`` to use the server's configured isolation level. However, Django
 | ||
| works best with and defaults to read committed rather than MySQL's default,
 | ||
| repeatable read. Data loss is possible with repeatable read. In particular,
 | ||
| you may see cases where :meth:`~django.db.models.query.QuerySet.get_or_create`
 | ||
| will raise an :exc:`~django.db.IntegrityError` but the object won't appear in
 | ||
| a subsequent :meth:`~django.db.models.query.QuerySet.get` call.
 | ||
| 
 | ||
| .. _transaction isolation level: https://dev.mysql.com/doc/refman/en/innodb-transaction-isolation-levels.html
 | ||
| 
 | ||
| Creating your tables
 | ||
| --------------------
 | ||
| 
 | ||
| When Django generates the schema, it doesn't specify a storage engine, so
 | ||
| tables will be created with whatever default storage engine your database
 | ||
| server is configured for. The easiest solution is to set your database server's
 | ||
| default storage engine to the desired engine.
 | ||
| 
 | ||
| If you're using a hosting service and can't change your server's default
 | ||
| storage engine, you have a couple of options.
 | ||
| 
 | ||
| * After the tables are created, execute an ``ALTER TABLE`` statement to
 | ||
|   convert a table to a new storage engine (such as InnoDB)::
 | ||
| 
 | ||
|       ALTER TABLE <tablename> ENGINE=INNODB;
 | ||
| 
 | ||
|   This can be tedious if you have a lot of tables.
 | ||
| 
 | ||
| * Another option is to use the ``init_command`` option for MySQLdb prior to
 | ||
|   creating your tables::
 | ||
| 
 | ||
|       'OPTIONS': {
 | ||
|          'init_command': 'SET default_storage_engine=INNODB',
 | ||
|       }
 | ||
| 
 | ||
|   This sets the default storage engine upon connecting to the database.
 | ||
|   After your tables have been created, you should remove this option as it
 | ||
|   adds a query that is only needed during table creation to each database
 | ||
|   connection.
 | ||
| 
 | ||
| Table names
 | ||
| -----------
 | ||
| 
 | ||
| There are `known issues`_ in even the latest versions of MySQL that can cause the
 | ||
| case of a table name to be altered when certain SQL statements are executed
 | ||
| under certain conditions. It is recommended that you use lowercase table
 | ||
| names, if possible, to avoid any problems that might arise from this behavior.
 | ||
| Django uses lowercase table names when it auto-generates table names from
 | ||
| models, so this is mainly a consideration if you are overriding the table name
 | ||
| via the :class:`~django.db.models.Options.db_table` parameter.
 | ||
| 
 | ||
| .. _known issues: https://bugs.mysql.com/bug.php?id=48875
 | ||
| 
 | ||
| Savepoints
 | ||
| ----------
 | ||
| 
 | ||
| Both the Django ORM and MySQL (when using the InnoDB :ref:`storage engine
 | ||
| <mysql-storage-engines>`) support database :ref:`savepoints
 | ||
| <topics-db-transactions-savepoints>`.
 | ||
| 
 | ||
| If you use the MyISAM storage engine please be aware of the fact that you will
 | ||
| receive database-generated errors if you try to use the :ref:`savepoint-related
 | ||
| methods of the transactions API <topics-db-transactions-savepoints>`. The reason
 | ||
| for this is that detecting the storage engine of a MySQL database/table is an
 | ||
| expensive operation so it was decided it isn't worth to dynamically convert
 | ||
| these methods in no-op's based in the results of such detection.
 | ||
| 
 | ||
| Notes on specific fields
 | ||
| ------------------------
 | ||
| 
 | ||
| .. _mysql-character-fields:
 | ||
| 
 | ||
| Character fields
 | ||
| ~~~~~~~~~~~~~~~~
 | ||
| 
 | ||
| Any fields that are stored with ``VARCHAR`` column types may have their
 | ||
| ``max_length`` restricted to 255 characters if you are using ``unique=True``
 | ||
| for the field. This affects :class:`~django.db.models.CharField`,
 | ||
| :class:`~django.db.models.SlugField`. See `the MySQL documentation`_ for more
 | ||
| details.
 | ||
| 
 | ||
| .. _the MySQL documentation: https://dev.mysql.com/doc/refman/en/create-index.html#create-index-column-prefixes
 | ||
| 
 | ||
| ``TextField`` limitations
 | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~
 | ||
| 
 | ||
| MySQL can index only the first N chars of a ``BLOB`` or ``TEXT`` column. Since
 | ||
| ``TextField`` doesn't have a defined length, you can't mark it as
 | ||
| ``unique=True``. MySQL will report: "BLOB/TEXT column '<db_column>' used in key
 | ||
| specification without a key length".
 | ||
| 
 | ||
| .. _mysql-fractional-seconds:
 | ||
| 
 | ||
| Fractional seconds support for Time and DateTime fields
 | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | ||
| 
 | ||
| MySQL can store fractional seconds, provided that the column definition
 | ||
| includes a fractional indication (e.g. ``DATETIME(6)``).
 | ||
| 
 | ||
| Django will not upgrade existing columns to include fractional seconds if the
 | ||
| database server supports it. If you want to enable them on an existing database,
 | ||
| it's up to you to either manually update the column on the target database, by
 | ||
| executing a command like::
 | ||
| 
 | ||
|     ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)
 | ||
| 
 | ||
| or using a :class:`~django.db.migrations.operations.RunSQL` operation in a
 | ||
| :ref:`data migration <data-migrations>`.
 | ||
| 
 | ||
| ``TIMESTAMP`` columns
 | ||
| ~~~~~~~~~~~~~~~~~~~~~
 | ||
| 
 | ||
| If you are using a legacy database that contains ``TIMESTAMP`` columns, you must
 | ||
| set :setting:`USE_TZ = False <USE_TZ>` to avoid data corruption.
 | ||
| :djadmin:`inspectdb` maps these columns to
 | ||
| :class:`~django.db.models.DateTimeField` and if you enable timezone support,
 | ||
| both MySQL and Django will attempt to convert the values from UTC to local time.
 | ||
| 
 | ||
| Row locking with ``QuerySet.select_for_update()``
 | ||
| -------------------------------------------------
 | ||
| 
 | ||
| MySQL and MariaDB do not support some options to the ``SELECT ... FOR UPDATE``
 | ||
| statement. If ``select_for_update()`` is used with an unsupported option, then
 | ||
| a :exc:`~django.db.NotSupportedError` is raised.
 | ||
| 
 | ||
| =============== ========= ==========
 | ||
| Option          MariaDB   MySQL
 | ||
| =============== ========= ==========
 | ||
| ``SKIP LOCKED`` X (≥10.6) X (≥8.0.1)
 | ||
| ``NOWAIT``      X         X (≥8.0.1)
 | ||
| ``OF``                    X (≥8.0.1)
 | ||
| ``NO KEY``
 | ||
| =============== ========= ==========
 | ||
| 
 | ||
| When using ``select_for_update()`` on MySQL, make sure you filter a queryset
 | ||
| against at least a set of fields contained in unique constraints or only
 | ||
| against fields covered by indexes. Otherwise, an exclusive write lock will be
 | ||
| acquired over the full table for the duration of the transaction.
 | ||
| 
 | ||
| Automatic typecasting can cause unexpected results
 | ||
| --------------------------------------------------
 | ||
| 
 | ||
| When performing a query on a string type, but with an integer value, MySQL will
 | ||
| coerce the types of all values in the table to an integer before performing the
 | ||
| comparison. If your table contains the values ``'abc'``, ``'def'`` and you
 | ||
| query for ``WHERE mycolumn=0``, both rows will match. Similarly, ``WHERE mycolumn=1``
 | ||
| will match the value ``'abc1'``. Therefore, string type fields included in Django
 | ||
| will always cast the value to a string before using it in a query.
 | ||
| 
 | ||
| If you implement custom model fields that inherit from
 | ||
| :class:`~django.db.models.Field` directly, are overriding
 | ||
| :meth:`~django.db.models.Field.get_prep_value`, or use
 | ||
| :class:`~django.db.models.expressions.RawSQL`,
 | ||
| :meth:`~django.db.models.query.QuerySet.extra`, or
 | ||
| :meth:`~django.db.models.Manager.raw`, you should ensure that you perform
 | ||
| appropriate typecasting.
 | ||
| 
 | ||
| .. _sqlite-notes:
 | ||
| 
 | ||
| SQLite notes
 | ||
| ============
 | ||
| 
 | ||
| Django supports SQLite 3.9.0 and later.
 | ||
| 
 | ||
| SQLite_ provides an excellent development alternative for applications that
 | ||
| are predominantly read-only or require a smaller installation footprint. As
 | ||
| with all database servers, though, there are some differences that are
 | ||
| specific to SQLite that you should be aware of.
 | ||
| 
 | ||
| .. _SQLite: https://www.sqlite.org/
 | ||
| 
 | ||
| .. _sqlite-string-matching:
 | ||
| 
 | ||
| Substring matching and case sensitivity
 | ||
| ---------------------------------------
 | ||
| 
 | ||
| For all SQLite versions, there is some slightly counter-intuitive behavior when
 | ||
| attempting to match some types of strings.  These are triggered when using the
 | ||
| :lookup:`iexact` or :lookup:`contains` filters in Querysets. The behavior
 | ||
| splits into two cases:
 | ||
| 
 | ||
| 1. For substring matching, all matches are done case-insensitively. That is a
 | ||
| filter such as ``filter(name__contains="aa")`` will match a name of ``"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 :lookup:`iexact` filter will behave exactly
 | ||
| the same as the :lookup:`exact` filter in these cases.
 | ||
| 
 | ||
| Some possible workarounds for this are `documented at sqlite.org`_, but they
 | ||
| aren't utilized by the default SQLite backend in Django, as incorporating them
 | ||
| would be fairly difficult to do robustly. Thus, Django exposes the default
 | ||
| SQLite behavior and you should be aware of this when doing case-insensitive or
 | ||
| substring filtering.
 | ||
| 
 | ||
| .. _documented at sqlite.org: https://www.sqlite.org/faq.html#q18
 | ||
| 
 | ||
| .. _sqlite-decimal-handling:
 | ||
| 
 | ||
| Decimal handling
 | ||
| ----------------
 | ||
| 
 | ||
| SQLite has no real decimal internal type. Decimal values are internally
 | ||
| converted to the ``REAL`` data type (8-byte IEEE floating point number), as
 | ||
| explained in the `SQLite datatypes documentation`__, so they don't support
 | ||
| correctly-rounded decimal floating point arithmetic.
 | ||
| 
 | ||
| __ https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
 | ||
| 
 | ||
| "Database is locked" errors
 | ||
| ---------------------------
 | ||
| 
 | ||
| SQLite is meant to be a lightweight database, and thus can't support a high
 | ||
| level of concurrency. ``OperationalError: database is locked`` errors indicate
 | ||
| that your application is experiencing more concurrency than ``sqlite`` can
 | ||
| handle in default configuration. This error means that one thread or process has
 | ||
| an exclusive lock on the database connection and another thread timed out
 | ||
| waiting for the lock the be released.
 | ||
| 
 | ||
| Python's SQLite wrapper has
 | ||
| a default timeout value that determines how long the second thread is allowed to
 | ||
| wait on the lock before it times out and raises the ``OperationalError: database
 | ||
| is locked`` error.
 | ||
| 
 | ||
| If you're getting this error, you can solve it by:
 | ||
| 
 | ||
| * Switching to another database backend. At a certain point SQLite becomes
 | ||
|   too "lite" for real-world applications, and these sorts of concurrency
 | ||
|   errors indicate you've reached that point.
 | ||
| 
 | ||
| * Rewriting your code to reduce concurrency and ensure that database
 | ||
|   transactions are short-lived.
 | ||
| 
 | ||
| * Increase the default timeout value by setting the ``timeout`` database
 | ||
|   option::
 | ||
| 
 | ||
|       'OPTIONS': {
 | ||
|           # ...
 | ||
|           'timeout': 20,
 | ||
|           # ...
 | ||
|       }
 | ||
| 
 | ||
|   This will make SQLite wait a bit longer before throwing "database is locked"
 | ||
|   errors; it won't really do anything to solve them.
 | ||
| 
 | ||
| ``QuerySet.select_for_update()`` not supported
 | ||
| ----------------------------------------------
 | ||
| 
 | ||
| SQLite does not support the ``SELECT ... FOR UPDATE`` syntax. Calling it will
 | ||
| have no effect.
 | ||
| 
 | ||
| .. _sqlite-isolation:
 | ||
| 
 | ||
| Isolation when using ``QuerySet.iterator()``
 | ||
| --------------------------------------------
 | ||
| 
 | ||
| There are special considerations described in `Isolation In SQLite`_ when
 | ||
| modifying a table while iterating over it using :meth:`.QuerySet.iterator`. If
 | ||
| a row is added, changed, or deleted within the loop, then that row may or may
 | ||
| not appear, or may appear twice, in subsequent results fetched from the
 | ||
| iterator. Your code must handle this.
 | ||
| 
 | ||
| .. _`Isolation in SQLite`: https://www.sqlite.org/isolation.html
 | ||
| 
 | ||
| .. _sqlite-json1:
 | ||
| 
 | ||
| Enabling JSON1 extension on SQLite
 | ||
| ----------------------------------
 | ||
| 
 | ||
| To use :class:`~django.db.models.JSONField` on SQLite, you need to enable the
 | ||
| `JSON1 extension`_ on Python's :py:mod:`sqlite3` library. If the extension is
 | ||
| not enabled on your installation, a system error (``fields.E180``) will be
 | ||
| raised.
 | ||
| 
 | ||
| To enable the JSON1 extension you can follow the instruction on
 | ||
| `the wiki page`_.
 | ||
| 
 | ||
| .. note::
 | ||
| 
 | ||
|     The JSON1 extension is enabled by default on SQLite 3.38+.
 | ||
| 
 | ||
| .. _JSON1 extension: https://www.sqlite.org/json1.html
 | ||
| .. _the wiki page: https://code.djangoproject.com/wiki/JSON1Extension
 | ||
| 
 | ||
| .. _oracle-notes:
 | ||
| 
 | ||
| Oracle notes
 | ||
| ============
 | ||
| 
 | ||
| Django supports `Oracle Database Server`_ versions 19c and higher. Version 7.0
 | ||
| or higher of the `cx_Oracle`_ Python driver is required.
 | ||
| 
 | ||
| .. _`Oracle Database Server`: https://www.oracle.com/
 | ||
| .. _`cx_Oracle`: https://oracle.github.io/python-cx_Oracle/
 | ||
| 
 | ||
| In order for the ``python manage.py migrate`` command to work, your Oracle
 | ||
| database user must have privileges to run the following commands:
 | ||
| 
 | ||
| * CREATE TABLE
 | ||
| * CREATE SEQUENCE
 | ||
| * CREATE PROCEDURE
 | ||
| * CREATE TRIGGER
 | ||
| 
 | ||
| To run a project's test suite, the user usually needs these *additional*
 | ||
| privileges:
 | ||
| 
 | ||
| * CREATE USER
 | ||
| * ALTER USER
 | ||
| * DROP USER
 | ||
| * CREATE TABLESPACE
 | ||
| * DROP TABLESPACE
 | ||
| * CREATE SESSION WITH ADMIN OPTION
 | ||
| * CREATE TABLE WITH ADMIN OPTION
 | ||
| * CREATE SEQUENCE WITH ADMIN OPTION
 | ||
| * CREATE PROCEDURE WITH ADMIN OPTION
 | ||
| * CREATE TRIGGER WITH ADMIN OPTION
 | ||
| 
 | ||
| While the ``RESOURCE`` role has the required ``CREATE TABLE``,
 | ||
| ``CREATE SEQUENCE``, ``CREATE PROCEDURE``, and ``CREATE TRIGGER`` privileges,
 | ||
| and a user granted ``RESOURCE WITH ADMIN OPTION`` can grant ``RESOURCE``, such
 | ||
| a user cannot grant the individual privileges (e.g. ``CREATE TABLE``), and thus
 | ||
| ``RESOURCE WITH ADMIN OPTION`` is not usually sufficient for running tests.
 | ||
| 
 | ||
| Some test suites also create views or materialized views; to run these, the
 | ||
| user also needs ``CREATE VIEW WITH ADMIN OPTION`` and
 | ||
| ``CREATE MATERIALIZED VIEW WITH ADMIN OPTION`` privileges. In particular, this
 | ||
| is needed for Django's own test suite.
 | ||
| 
 | ||
| All of these privileges are included in the DBA role, which is appropriate
 | ||
| for use on a private developer's database.
 | ||
| 
 | ||
| The Oracle database backend uses the ``SYS.DBMS_LOB`` and ``SYS.DBMS_RANDOM``
 | ||
| packages, so your user will require execute permissions on it. It's normally
 | ||
| accessible to all users by default, but in case it is not, you'll need to grant
 | ||
| permissions like so:
 | ||
| 
 | ||
| .. code-block:: sql
 | ||
| 
 | ||
|     GRANT EXECUTE ON SYS.DBMS_LOB TO user;
 | ||
|     GRANT EXECUTE ON SYS.DBMS_RANDOM TO user;
 | ||
| 
 | ||
| Connecting to the database
 | ||
| --------------------------
 | ||
| 
 | ||
| To connect using the service name of your Oracle database, your ``settings.py``
 | ||
| file should look something like this::
 | ||
| 
 | ||
|     DATABASES = {
 | ||
|         'default': {
 | ||
|             'ENGINE': 'django.db.backends.oracle',
 | ||
|             'NAME': 'xe',
 | ||
|             'USER': 'a_user',
 | ||
|             'PASSWORD': 'a_password',
 | ||
|             'HOST': '',
 | ||
|             'PORT': '',
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
| In this case, you should leave both :setting:`HOST` and :setting:`PORT` empty.
 | ||
| However, if you don't use a ``tnsnames.ora`` file or a similar naming method
 | ||
| and want to connect using the SID ("xe" in this example), then fill in both
 | ||
| :setting:`HOST` and :setting:`PORT` like so::
 | ||
| 
 | ||
|     DATABASES = {
 | ||
|         'default': {
 | ||
|             'ENGINE': 'django.db.backends.oracle',
 | ||
|             'NAME': 'xe',
 | ||
|             'USER': 'a_user',
 | ||
|             'PASSWORD': 'a_password',
 | ||
|             'HOST': 'dbprod01ned.mycompany.com',
 | ||
|             'PORT': '1540',
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
| You should either supply both :setting:`HOST` and :setting:`PORT`, or leave
 | ||
| both as empty strings. Django will use a different connect descriptor depending
 | ||
| on that choice.
 | ||
| 
 | ||
| Full DSN and Easy Connect
 | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~
 | ||
| 
 | ||
| A Full DSN or Easy Connect string can be used in :setting:`NAME` if both
 | ||
| :setting:`HOST` and :setting:`PORT` are empty. This format is required when
 | ||
| using RAC or pluggable databases without ``tnsnames.ora``, for example.
 | ||
| 
 | ||
| Example of an Easy Connect string::
 | ||
| 
 | ||
|     'NAME': 'localhost:1521/orclpdb1',
 | ||
| 
 | ||
| Example of a full DSN string::
 | ||
| 
 | ||
|     'NAME': (
 | ||
|         '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))'
 | ||
|         '(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))'
 | ||
|     ),
 | ||
| 
 | ||
| Threaded option
 | ||
| ---------------
 | ||
| 
 | ||
| If you plan to run Django in a multithreaded environment (e.g. Apache using the
 | ||
| default MPM module on any modern operating system), then you **must** set
 | ||
| the ``threaded`` option of your Oracle database configuration to ``True``::
 | ||
| 
 | ||
|     'OPTIONS': {
 | ||
|         'threaded': True,
 | ||
|     },
 | ||
| 
 | ||
| Failure to do this may result in crashes and other odd behavior.
 | ||
| 
 | ||
| INSERT ... RETURNING INTO
 | ||
| -------------------------
 | ||
| 
 | ||
| By default, the Oracle backend uses a ``RETURNING INTO`` clause to efficiently
 | ||
| retrieve the value of an ``AutoField`` when inserting new rows.  This behavior
 | ||
| may result in a ``DatabaseError`` in certain unusual setups, such as when
 | ||
| inserting into a remote table, or into a view with an ``INSTEAD OF`` trigger.
 | ||
| The ``RETURNING INTO`` clause can be disabled by setting the
 | ||
| ``use_returning_into`` option of the database configuration to ``False``::
 | ||
| 
 | ||
|     'OPTIONS': {
 | ||
|         'use_returning_into': False,
 | ||
|     },
 | ||
| 
 | ||
| In this case, the Oracle backend will use a separate ``SELECT`` query to
 | ||
| retrieve ``AutoField`` values.
 | ||
| 
 | ||
| Naming issues
 | ||
| -------------
 | ||
| 
 | ||
| Oracle imposes a name length limit of 30 characters. To accommodate this, the
 | ||
| backend truncates database identifiers to fit, replacing the final four
 | ||
| characters of the truncated name with a repeatable MD5 hash value.
 | ||
| Additionally, the backend turns database identifiers to all-uppercase.
 | ||
| 
 | ||
| To prevent these transformations (this is usually required only when dealing
 | ||
| with legacy databases or accessing tables which belong to other users), use
 | ||
| a quoted name as the value for ``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"'
 | ||
| 
 | ||
| Quoted names can also be used with Django's other supported database
 | ||
| backends; except for Oracle, however, the quotes have no effect.
 | ||
| 
 | ||
| When running ``migrate``, an ``ORA-06552`` error may be encountered if
 | ||
| certain Oracle keywords are used as the name of a model field or the
 | ||
| value of a ``db_column`` option.  Django quotes all identifiers used
 | ||
| in queries to prevent most such problems, but this error can still
 | ||
| occur when an Oracle datatype is used as a column name.  In
 | ||
| particular, take care to avoid using the names ``date``,
 | ||
| ``timestamp``, ``number`` or ``float`` as a field name.
 | ||
| 
 | ||
| .. _oracle-null-empty-strings:
 | ||
| 
 | ||
| NULL and empty strings
 | ||
| ----------------------
 | ||
| 
 | ||
| Django generally prefers to use the empty string (``''``) rather than
 | ||
| ``NULL``, but Oracle treats both identically. To get around this, the
 | ||
| Oracle backend ignores an explicit ``null`` option on fields that
 | ||
| have the empty string as a possible value and generates DDL as if
 | ||
| ``null=True``. When fetching from the database, it is assumed that
 | ||
| a ``NULL`` value in one of these fields really means the empty
 | ||
| string, and the data is silently converted to reflect this assumption.
 | ||
| 
 | ||
| ``TextField`` limitations
 | ||
| -------------------------
 | ||
| 
 | ||
| The Oracle backend stores ``TextFields`` as ``NCLOB`` columns. Oracle imposes
 | ||
| some limitations on the usage of such LOB columns in general:
 | ||
| 
 | ||
| * LOB columns may not be used as primary keys.
 | ||
| 
 | ||
| * LOB columns may not be used in indexes.
 | ||
| 
 | ||
| * LOB columns may not be used in a ``SELECT DISTINCT`` list. This means that
 | ||
|   attempting to use the ``QuerySet.distinct`` method on a model that
 | ||
|   includes ``TextField`` columns will result in an ``ORA-00932`` error when
 | ||
|   run against Oracle. As a workaround, use the ``QuerySet.defer`` method in
 | ||
|   conjunction with ``distinct()`` to prevent ``TextField`` columns from being
 | ||
|   included in the ``SELECT DISTINCT`` list.
 | ||
| 
 | ||
| .. _subclassing-database-backends:
 | ||
| 
 | ||
| Subclassing the built-in database backends
 | ||
| ==========================================
 | ||
| 
 | ||
| Django comes with built-in database backends. You may subclass an existing
 | ||
| database backends to modify its behavior, features, or configuration.
 | ||
| 
 | ||
| Consider, for example, that you need to change a single database feature.
 | ||
| First, you have to create a new directory with a ``base`` module in it. For
 | ||
| example::
 | ||
| 
 | ||
|     mysite/
 | ||
|         ...
 | ||
|         mydbengine/
 | ||
|             __init__.py
 | ||
|             base.py
 | ||
| 
 | ||
| The ``base.py`` module must contain a class named ``DatabaseWrapper`` that
 | ||
| subclasses an existing engine from the ``django.db.backends`` module. Here's an
 | ||
| example of subclassing the PostgreSQL engine to change a feature class
 | ||
| ``allows_group_by_selected_pks_on_model``:
 | ||
| 
 | ||
| .. code-block:: python
 | ||
|     :caption: ``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
 | ||
| 
 | ||
| Finally, you must specify a :setting:`DATABASE-ENGINE` in your ``settings.py``
 | ||
| file::
 | ||
| 
 | ||
|     DATABASES = {
 | ||
|         'default': {
 | ||
|             'ENGINE': 'mydbengine',
 | ||
|             ...
 | ||
|         },
 | ||
|     }
 | ||
| 
 | ||
| You can see the current list of database engines by looking in
 | ||
| :source:`django/db/backends`.
 | ||
| 
 | ||
| .. _third-party-notes:
 | ||
| 
 | ||
| Using a 3rd-party database backend
 | ||
| ==================================
 | ||
| 
 | ||
| In addition to the officially supported databases, there are backends provided
 | ||
| by 3rd parties that allow you to use other databases with Django:
 | ||
| 
 | ||
| * `CockroachDB`_
 | ||
| * `Firebird`_
 | ||
| * `Google Cloud Spanner`_
 | ||
| * `Microsoft SQL Server`_
 | ||
| * `TiDB`_
 | ||
| * `YugabyteDB`_
 | ||
| 
 | ||
| The Django versions and ORM features supported by these unofficial backends
 | ||
| vary considerably. Queries regarding the specific capabilities of these
 | ||
| unofficial backends, along with any support queries, should be directed to
 | ||
| the support channels provided by each 3rd party project.
 | ||
| 
 | ||
| .. _CockroachDB: https://pypi.org/project/django-cockroachdb/
 | ||
| .. _Firebird: https://pypi.org/project/django-firebird/
 | ||
| .. _Google Cloud Spanner: https://pypi.org/project/django-google-spanner/
 | ||
| .. _Microsoft SQL Server: https://pypi.org/project/mssql-django/
 | ||
| .. _TiDB: https://pypi.org/project/django-tidb/
 | ||
| .. _YugabyteDB: https://pypi.org/project/django-yugabytedb/
 |