Basisdata

Django officially supports the following databases:

There are also a number of database backends provided by third parties.

Django berusaha mendukung sebanyak mungkin fitur-fitur pada semua backend basisdata. bagaimanapun, tidak semua backend basisdata sama, dan kami harus membuat perancangan keputusan pada dimana fitur-fitur untuk mendukung dan dimana anggapan kami dapat membuat aman.

Berkas ini menggambarkan beberapa fitur yang mungkin terkait pada penggunaan Django. Tentu saja, itu tidak dimaksudkan sebagai sebuah pengganti untuk dokumentasi peladen-khusus atau manual acuan.

Catatan umum

Hubungan tetap

Hubungan tetap menghindari kelebihan dari pembangunan-kembali sebuah hubungan pada basisdata dalam setiap permintaan. mereka dikendalikan dengan parameter CONN_MAX_AGE yang menentukan umur waktu maksimal dari setiap hubungan. Itu dapat disetel secara berdiri sendiri untuk setiap basisdata.

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 CONN_MAX_AGE to a positive integer of seconds. For unlimited persistent connections, set it to None.

Pengelolaan hubungan

Django membua sebuah hubungan pada basisdata ketika itu pertama kali membuat sebuah permintaan basisdata. Itu menjaga hubungan ini tetap terbuka dan menggunakan kembali itu dalam permintaan selanjutnya. Django menutup hubungan sekali itu melampau batas umur maksimal ditentukan oleh CONN_MAX_AGE atau ketika itu tidak digunakan lagi.

Secara terperinci, Django otomatis membuha sebuah hubungan pada basisdata kapanpun dia membutuhkan satu dan tidak mempunyai satu -- baik karena ini adalah hubungan pertama, atau karena hubungan sebelumnya telah ditutup.

Pada permulaan dari setiap permintaan, Django menutup hubungan jika itu telah mencapai umur maksimal. Jika basisdata anda memutuskan hubungan diam setelah beberapa waktu, anda harus menyetel CONN_MAX_AGE pada nilai terendah, sehingga Django tidak berusaha menggunakan hubungan yang telah diputus oleh peladen basisdata. (Masalah ini mungkin hanya berpengaruh situs lalu lintas sangat rendah.)

Pada akhir dari setiap permintaan, Django menutup hubungan jika itu telah mencapai umur maksimalnya atau jika itu dalam keadaan kesalahan yang tidak dapat ditutup. Jika kesalahan basisdata apapun telah muncul selagi mengolah permintaan, Django memeriksa apakah hubungan masih bekerja, dan menutup itu jika itu tidak. Dengan demikian, kesalahan basisdata mempengaruhi kebanyakan satu permintaan; jika hubungan menjadi tidak berguna, permintaan selanjutnya mendapatkan hubungan segar.

Peringatan

Sejak setiap thread merawat hubungan dia sendiri, basisdata anda harus mendukung setidaknya sebanyak hubungan serentak ketika anda memiliki thread pekerja.

Terkadang sebuah basisdata tidak mau diakses oleh kebanyakan dari tampilan anda, sebagai contoh karena itu adalah basisdata dari sebuah sistem luar, atau terima kasih ke penyimpanan sementara. Dalam kasus-kasus itu, anda harus mensetel CONN_MAX_AGE menjadi nilai rendah atau bahkan 0, karena itu tidak masuk akal merawat sebuah hubungan untuk digunakan kembali. Ini akan membantu menjaga sejumlah hubungan serentak pada basisdata kecil ini.

Peladen pengembangan membuat sebuah thread baru untuk setiap permintaan dia tangani, meniadakan pengaruh dari hubungan tetap. Jangan mengadakan mereka selama pengembangan.

Ketika Django membangun sebuah hubungan ke basisdata, dia menyetel parameter yang sesuai, tergantung pada backend sedang digunakan. Jika anda mengadakan hubungan tetap, pengaturan ini tidak lagi berulang setiap permintaan. jika anda merubah parameter seperti tingkat pemisahan hubungan atau zona waktu, anda harus baik menyimpan kembali awalan Django pada akhir setiap permintaan, memaksa sebuah nilai sesuai pada permulaan dari setiap permintaan, atau meniadakan hubungan tetap.

Penyandian

Django menganggap bahwa semua basisdata menggunakan penyandian UTF-8. Menggunakan penyandian lain mungkn menghasilkan perilaku tidak diharapkan seperti kesalahan "nilai terlalu panjang" dari basisdata anda untuk data yang sah dalam Django. Lihat basisdata catatan khusus dibawah untuk informasi pada bagaimana menyetel basisdata anda dengan benar.

Catatan PostgreSQL

Django supports PostgreSQL 9.5 and higher. psycopg2 2.5.4 or higher is required, though the latest release is recommended.

Pengaturan hubungan PostgreSQL

Lihat HOST untuk rincian.

Mengoptimalkan konfigurasi PostgreSQL

Django butuh parameter berikut untuk hubungan basisdatanya:

  • client_encoding: 'UTF8',
  • default_transaction_isolation: 'read committed' secara awalan, atau nilai disetel dalam pilihan hubungan (lihat dibawah),
  • timezone: 'UTC' ketika USE_TZ adalah True, nilai TIME_ZONE sebaliknya.

Jika parameter ini sudah memiliki nilai benar, Django tidak akan mensetel mereka untuk setiap hubugan baru, yang which memperbaiki sedikit penampilan. Anda dapat menkonfigurasi mereka langsung dalam postgresql.conf atau lebih nyaman per pengguna basisdata ALTER ROLE.

Django akan bekerja baik tanpa optimalisasi ini, tetapi setiap hubungan baru akan melakukan beberapa permintaan untuk mensetel parameter ini.

Tingkat terpencil

Seperti PostgreSQL itu sendiri, awalan Django pada READ COMMITTED isolation level. Jika anda butuh tingkat terpencil tertinggi seperti REPEATABLE READ atau SERIALIZABLE, setel itu dalam bagian OPTIONS dari konfigurasi basisdata anda dalam DATABASES:

import psycopg2.extensions

DATABASES = {
    # ...
    'OPTIONS': {
        'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE,
    },
}

Catatan

Dibawah tingkat terpencil tertinggi, aplikasi anda harus dipersiapkan menangani pengecualian dimunculkan pada kegagalan serialisasi. Pilihan ini dirancang untuk pengguna lanjut.

Indeks untuk kolom varchar dan text

Ketika menentukan db_index=True pada bidang model anda, Django khususnya mengeluarkan pernyataan tunggal CREATE INDEX. Bagaimanapun, jika jenis basisdata untuk bidang adalah baik salah satu varchar atau text (misalnya, digunakan oleh CharField, FileField, dan TextField), kemudian Django akan membuat sebuah indeks tambahan yang menggunakan PostgreSQL operator class untuk kolom. Indeks tambahan diperlukan untuk dengan benar melakukan pencarian yang menggunakan penghubung LIKE dalam SQL mereka, ketika selesai dengan jenis pencarian contains dan startswith.

Tindakan perpindahan untuk menambahkan tambahan.

Jika anda butuh menambahkan sebuah tambahan PostgreSQL (seperti hstore, postgis, dll.) menggunakan perpindahan, gunakan tindakan CreateExtension.

Kursor sisi-peladen

Ketika menggunakan QuerySet.iterator(), Django membuka sebuah server-side cursor. Secara awalan, PostgreSQL menganggap bahwa hanya 10% pertama dari hasil dari kursor permintaan akan diambil. Perencana penerimaan menghabiskan sedikit waktu merencanakan permintaan dan memulai mengembalikan hasil lebih cepat, tetapi ini dapat mengurangi penampilan jika lebih dari 10% dari hasil diambil. Anggapan PostgreSQL pada angka baris diambil untuk kursor permintaan dikendalikan dengan pilihan cursor_tuple_fraction.

Menggabungkan transaksi dan kursor sisi-peladen

Using a connection pooler in transaction pooling mode (e.g. PgBouncer) requires disabling server-side cursors for that connection.

Kursos sisi-peladen adalah lokal terhadap sebuah hubungan dan tetap terbuka pada akhir dari sebuah transaksi ketika AUTOCOMMIT adalah True. Sebuah transaksi seanjutnya mungkin berusaha mengambil hasil lebih dari kursor sisi-peladen. Dalam suasana pengumpulan transaksi, tidak ada jaminan bahwa transaksi sebelumnya akan menggunakan hubungan sama. Jika sebuah hubungan berbeda digunakan, sebuah kesalahan dimunculkan ketika transaksi mengacu kursor sisi-peladen, karena kursos sisi-peladen hanya tersedia dalam hubungan dimana mereka dibuat.

Satu pemecahan adalah untuk meniadakan kursor sisi peladen untuk sebuah hubungan adalah DATABASES by setting DISABLE_SERVER_SIDE_CURSORS menjadi True.

Keuntungan dari kursor sisi-peladen dalam suasana penggabungan transaksi, anda dapat menyetel another connection to the database untuk melakukan permintaan yang menggunakan kursor sisi-peladen. Hubungan ini butuh salah satu langsung ke basisdata atau ke hubungan pengumpulan dalam suasana sesi pengumpulan.

Pilihan lain adalah membungkus setiap QuerySet menggunakan kursor sisi-peladen dalam sebuah blok atomic(), karena itu meniadakan autocommit untuk lamanya transaksi. Cara ini, kursor sisi-peladen akan hanya tinggal untuk selama transaksi.

Manual-menentukan nilai-nilai dari primary key peningkatan-otomatis

Django menggunakan SERIAL data type PostgreSQL untuk menyimpan peningkatan-otomatis primary key. Sebuah kolom SERIAL dihitung dengan nilai-nilai dari sequence yang menjaga nilai ketersediaan selanjutnya. Secara manual memberikan nilai pada sebuah bidang peningkatan-otomatis tidak memperbaharui urutan bidang, yang mungkin kemudian menyebabkan sebuah pertentangan. Sebagai contoh:

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

Jika anda butuh menentukan nilai-nilai seperti itu, setel kembali urutan setelah itu menghindari menggunakan sebuah nilai yang sudah dalam tabel. Perintah pengelolaan sqlsequencereset membangkitkan pernyataan SQL untuk melakukan itu.

Cetakan percobaan basisdata

Anda dapat menggunakan pengaturan TEST['TEMPLATE'] untuk menentukan template (misalnya 'template0') dari mana membuat basis data percobaan.

Mempercepat penjalanan percobaan dengan pengaturan tidak-tahan-lama

Anda dapat mempercepat waktu penjalanan percobaan dengan configuring PostgreSQL to be non-durable.

Peringatan

Ini sangat berbahaya: itu akan membuat basisdata anda lebih rentan terhadap kehilangan data atau korupsi dalam kasus dari peladen roboh atau kehilangan daya. Gunakan ini hanya pada mesin pengembangan dimana anda dapat dengan mudah menyimpan kembali seluruh isi dari semua basisdata dalam gugus.

MariaDB notes

New in Django 3.0.

Django supports MariaDB 10.1 and higher.

To use MariaDB, use the MySQL backend, which is shared between the two. See the MySQL notes for more details.

Catatan MySQL

Versi dukungan

Django mendukung MySQL 5.6 dan lebih tinggi.

Fitur inspectdb Django menggunakan basisdata information_schema, yang mengandung rincian data pada semua skema basisdata.

Django mengharapkan basisdata untuk mendukung Unicode (UTF-8 encoding) dan menugaskan ke itu tugas dari memaksa transaksi dan keutuhan referensial. itu adalah penting untuk waspada dari fakta bahwa dua terakhir sebenarnya tidak dipaksa oleh MySQL ketika menggunakan mesin penyimpanan, lihat bagian selanjutnya.

Mesin penyimpanan

MySQL mempunyai beberapa storage engines. Anda dapat merubah mesin penyimpanan awalan dalam konfigurasi peladen.

Mesin penyimpanan awalan MySQL adalah InnoDB. Mesin ini sepenuhnya transaksional dan mendukung acuan foreign key. Itu adalah pilihan dianjurkan. Bagaimanapun penghitung peningkatan otomatis InnoDB hilang pada pemulaian kembali MySQL karena itu tidak ingat nilai AUTO_INCREMENT, daripada membuat kembali itu sebagai "max(id)+1". Ini mungkin menghasilkan sebuah penggunaan kembali tidak sengaja dari nilai AutoField.

Kekurangan utama dari MyISAM adalah bahwa itu tidak mendukung transaksi atau memaksa batasan foreign-key.

Driver API DB MySQL

MySQL mempunyai sepasang driver yang menerapkan API Basisdata Python digambarkan dalam PEP 249:

  • mysqlclient adalah pengemudi asli. Itu adalah pilihan dianjurkan.
  • MySQL Connector/Python adalah murni pengemudi Python dari Oracle yang tidak mewajibkan pustaka klien MySQL atau modul Python apapun diluar dari pustaka standar.

Pengemudi ini adalah untaian-aman dan menyediakan hubungan menyatukan.

Sebagai tambahan pada pengemudi API DB, Django butuh sebuah penyadur mengakses pengemudi basisdata dari ORM nya. Django menyediakan sebuah penyadur untuk mysqlclient selagi Penghubung/Python MySQL termasuk its own.

mysqlclient

Django membutuhkan mysqlclient 1.3.13 atau terakhir

Penghubung MySQL/Python

Penghubung/Python MySQL tersedia dari download page. Penyadur Django tersedia dalam versi 1.1.X dan terakhir. itu mungkin tidak mendukung kebanyakan terbitan terakhir dari Django.

Pengertian zona waktu

Jika anda berencana menggunakan dukungan timezone Django, gunakan mysql_tzinfo_to_sql untuk memuat tabel zona waktu kedalam basisdata MySQL. Ini harus dilakukan hanya sekali untuk peladen MySQL anda, bukan per basisdata.

Membuat basisdata anda

Anda dapat membuat basisdata anda menggunakan alat baris-perintah dan SQL ini:

CREATE DATABASE <dbname> CHARACTER SET utf8;

Ini memastikan semua tabel dan kolom akan menggunakan UTF-8 secara awal.

Pengaturan pemeriksaan

Pengaturan pemeriksaan untuk sebuah kolom mengendalikan urutan dimana data diurutkan sama halnya dengan string apa dibandingkan sebagai setara. Itu dapat disetel pada tingkat luas-basisdata dan juga per-tabel dan per-kolom. Itu adalah documented thoroughly dalam dokumentasi MySQL. Dalam semua kasus, anda menyetel pemeriksaan dengan langsung merubah tabel-tabel basisdata; Django tidak menyediakan cara mensetel ini pada sebuah pengertian model.

Secara awalan, dengan basisdata UTF-8, MySQL akan menggunakan pemeriksaan utf8_general_ci. Ini menghasilkan dalam semua kesetaraan pembandingan string sedang diselesaikan dalam cara kasus-tidak-peka. Yaitu, "Fred" dan "freD" dianggap tidak sah untuk mencoba memasukkan kedua "aa" and "AA" kedalam kolom sama, sejak mereka membandingkan sebagai kesetaraan (dan, karenanya, bukan-unik) dengan pemeriksaan awalan. Jika anda ingin perbandingan kasus-peka pada kolom atau tabel tertentu, rubah kolom atau tabel untuk menggunakan pemeriksaan utf8_bin.

Harap catat bahwa menurut MySQL Unicode Character Sets, perbandingan untuk pemeriksaan utf8_general_ci adalah lebih cepat, tetapi sedikit kurang benar, daripada perbandingan untuk utf8_unicode_ci. Jika ini diterima untuk aplikasi anda, anda harus menggunakan utf8_general_ci karena itu lebih cepat. Jika ini tidak diterima (sebagai contoh, jika anda membutuhkan urutan kamus Jerman), gunakan utf8_unicode_ci karena itu lebih akurat.

Peringatan

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.

Menyambung ke basisdata

Mengacu ke pengaturan dokumentasi.

Pengaturan hubungan digunakan dalam urutan ini:

  1. OPTIONS.
  2. NAME, USER, PASSWORD, HOST, PORT
  3. Berkas pilihan MySQL.

Dengan kata lain, jika anda mensetel nama dari basisdata dalam OPTIONS, ini akan mengambil hak lebih tinggi terhadap NAME, yang akan menimpa apapin dalam MySQL option file.

Ini adalah contoh konfigurasi yang menggunakan berkas pilihan 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 = utf8

Beberapa MySQLdb connection options lain mungkin berguna, seperti ssl, init_command, dan sql_mode.

Mengatur sql_mode

Dari MySQL 5.7 selanjutnya dan pada pemasangan segar dari MySQL 5.6, nilai awalan dari pilihan sql_mode mengandung STRICT_TRANS_TABLES. Pilihan itu meningkatkan peringatan menjadi kesalahan ketika data dipotong ketika pemasukan, jadi Django sangat menganjurkan mengaktifkan strict mode untuk MySQL mencegah kehilangan data (antara STRICT_TRANS_TABLES atau STRICT_ALL_TABLES).

Jika anda butuh menyesuaiakan suasana SQL, anda dapat mensetel variabel sql_mode seperti pilihan MySQL lain: antara dalam berkas konfigurasi atau dengan masukan 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'" dalam bagian OPTIONS dari konfigurasi basisdata anda dalam DATABASES.

Tingkat terpencil

Ketika menjalankan pemuatan yang bersamaan, transaksi basisdata dari sesi-sesi berbeda (katakan, urutan lain menangani permintaan berbeda) mungkin berinteraksi dengan satu sama lain. Interaksi ini mungkin dipengaruhi oleh setiap transaction isolation level sesi. Anda dapat mensetel tingkat terpencil hubungan dengan sebuah masukan 'isolation_level' dalam OPTIONS bagian dari konfigurasi basisdata anda dalam DATABASES. Nilai sah untuk masukan ini adalah empat sandar tingkat terpencil:

  • '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 get_or_create() will raise an IntegrityError but the object won't appear in a subsequent get() call.

Membuat tabel anda

Ketika Django membangkitkan skema, itu tidak menentukan sebuah mesin penyimpanan, jadi tabel-tabel akan dibuat dengan apapun mesin penyimpanan awalan paladen basisdata anda dikonfigurasikan. Pemecahan paling mudah adalah mensetel mesin penyimpanan awalan peladen basisdata anda pada mesin yang diinginkan.

Jika anda sedang menggunakan layanan rumahan dan tidak dapat merubah mesin penyimpanan awalan peladen, anda memiliki sepasang pilihan.

  • Setelah tabel dibuat, jalankan sebuah pernyataan ALTER TABLE untuk merubah sebuah tabel ke mesin penyimpanan baru (seperti InnoDB):

    ALTER TABLE <tablename> ENGINE=INNODB;
    

    Ini dapat membosankan jika anda memiliki banyak tabel.

  • Pilihan lain adalah menggunakan pilihan init_command untuk MySQLdb sebelum membuat tabel anda:

    'OPTIONS': {
       'init_command': 'SET default_storage_engine=INNODB',
    }
    

    Ini menyetel mesin penyimpanan awalan diatas hubungan ke basisdata. Setelah tabel-tabel anda telah dibuat, anda harus memindahkan pilihan ini ketika itu menambahkan sebuah permintaan yaitu hanya dibutuhkan selama pembautan tabel pada setiap hubungan basisdata.

Nama tabel

Ada known issues di bahkan versi terakhir dari MySQL yang dapat menyebabkan kasus dari nama tabel dirubah ketika pernyataan SQL tertentu dijalankan dibawah kondisi tertentu. Itu dianjurkan bahwa anda menggunakan nama tabel huruf kecil, jika memungkinkan, untuk menghindari masalah apapun yang mungkin muncul dari perilaku ini. Django menggunakan nama tabel huruf kecil ketika it membangkitkan-otomatis nama tabel dari mdoel, jadi ini adalah pertimbangan utama jika anda sedang menimpa nama tabel melalui parameter db_table.

Savepoint

Kedua ORM Django dan MySQL (ketika menggunakan InnoDB storage engine) mendukung basisdata 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 savepoint-related methods of the transactions API. 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.

Catatan pada tabel khusus

Bidang karakter

Bidang-bidang apapun yang disimpan dengan jenis kolom VARCHAR memiliki max_length nya dibatasi pada 255 karakter jika anda sedang menggunakan unique=True untuk bidang. Ini mempengaruhi CharField, SlugField.

Batasan TextField

MySQL hanya dapat mengindeks karakter N pertama dari kolom BLOB atau TEXT. Sejak TextField tidak memiliki panjang yang ditentukan, anda tidak dapat menanda itu sebagai unique=True. MySQLakan melaporkan: "kolom BLOB/TEXT '<db_column>' digunakan dalam spesifikasi kunci tanpa panjang kunci".

Pecahan kedua mendukung untuk bidang Time dan DateTime

MySQL 5.6.4 dan kemudian dapat menyimpan store bagian detik, disediakan bahwa pengertian kolom termasuk petunjuk bagian (e.g. DATETIME(6)). Versi paling awal tidak mendukung mereka semua.

Django tidak akan meningkatkan kolom yang ada untuk menyertakan bagian detik jika peladen basisdata mendukung itu. Jika anda ingin mengadakan mereka pada basisdata yang ada, itu terserah anda baik secara manual memperbaharui kolom pada basisdata sasaran, dengan menjalankan sebuah perintah seperti:

ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)

atau menggunakan tindakan RunSQL dalam data migration.

Kolom TIMESTAMP

Jika anda menggunakan sebuah basisdata warisan yang mengandung kolom TIMESTAMP, anda harus mensetel USE_TZ = False untuk menghindari kerusakan data. inspectdb memetakan kolom-kolom ini pada DateTimeField dan jika anda mengadakan dukungan zona waktu, kedua MySQL dan Django akan berusaha merubah nilai-nilai dari UTC ke waktu lokal.

Penguncian baris dengan 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 NotSupportedError is raised.

Option MariaDB MySQL
SKIP LOCKED   X (≥8.0.1)
NOWAIT X (≥10.3) X (≥8.0.1)
OF    

When using select_for_update() on MySQL, make sure you filter a queryset against at least 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.

Typecasting otomatis dapat menggunakan hasil tidak diharapkan

Ketika melakukan sebuah permintaan pada jenis string, tetapi dengan sebuah nilai integer, MySQL akan memaksa jenis-jenis dari semua nilai dalam tabel pada sebuah integer sebelum melakukan perbandingan. Jika tabel-tabel anda mengandung nilai 'abc', 'def' dan permintaan anda untuk WHERE mycolumn=0, kedua baris akan cocok. Mirip, WHERE mycolumn=1 akan cocok nilai 'abc1'. Karena itu, bidang-bidang jenis string disertakan dalam Django akan selalu melempar nilai ke sebuah string sebelum menggunakan itu dalam sebuah permintaan.

Jika anda menerapkan bdiang model penyesuaian yang mewarisi dari Field directly, adalah menimpa get_prep_value(), atau menggunakan RawSQL, extra(), atau raw(), anda harus memastikan bahwa anda melakukan typecasting yang sesuai.

Catatan SQLite

Django mendukung SQLite 3.8.3 dan terakhir.

SQLite menyediakan cara lain pengembangan yang bagus untuk aplikasi-aplikasi yang terutama hanya-baca atau membutuhkan jejak kaki pemasangan terkecil. Seperti semua peladen basisdata, meskipun, ada beberapa perbendaan yang khusus pada SQLite yang anda harus waspadai.

Substring matching and case sensitivity

Untuk semua versi SQLite, ada beberapa perilaku sedikit kontra-intuitif ketika berusaha mencocokkan beberapa jenis string. Ini dibangkitkan ketika menggunakan penyaring iexact atau contains dalam Queryset. Perilaku ini memecah menjadi dua kasus:

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 iexact filter will behave exactly the same as the 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.

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.

Kesalahan "Basisdata terkunci"

SQLite berarti menjadi basisdata ringan, dan demikian tidak dapat mendukung bersamaan tingkat tinggi. Kesalahan OperationalError: bassidata dikunci menunjukkan bahwa aplikasi anda berpengalaman lebih bersamaan daripada sqlite dapat tangani dalam konfigurasi awalan. Kesalahan ini berarti bahwa satu antrian atau proses mempunyai sebuah kunci khusus pada hubungan basisdata dan waktu habis antrian lain menunggu untuk kunci dibebaskan.

Pembungkus SQLite Python mempunyai nilai waktu habis awalan yang menentukan seberapa lama detik urutan diizinkan untuk menunggu penguncian sebelum itu berakhir dan memunculkan kesalahan OperationalError: database is locked.

Jika anda mendapatkan kesalahan ini, anda dapat menyelesaikannya dengan:

  • Berganti ke backend basisdata lain. Pada titik tertentu SQLite menjadi terlalu "ringan" untuk aplikasi dunia-sebenarnya, dan urutan kesalahan bersamaan ini menunjukkan anda telah mencapat titik itu.

  • Menulis kembali kode anda untuk mengurangi bersamaan dan memastikan transaksi basisdata adalah berumur-pendek.

  • Meningkatkan nilai waktu habis awalan dengan mengatur pilihan basisdata timeout:

    '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() tidak didukung

SQLite tidak mendukung sintaksis SELECT ... FOR UPDATE. Memanggil itu tidak akan memiliki pengaruh.

Gaya parameter "pyformat" dalam permintaan mentah tidak didukung

For most backends, raw queries (Manager.raw() or cursor.execute()) can use the "pyformat" parameter style, where placeholders in the query are given as '%(name)s' and the parameters are passed as a dictionary rather than a list. SQLite does not support this.

Pengucilan ketika menggunakan QuerySet.iterator()

There are special considerations described in Isolation In SQLite when modifying a table while iterating over it using 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.

Catatan Oracle

Django supports Oracle Database Server versions 12.2 and higher. Version 6.0 or higher of the cx_Oracle Python driver is required.

Untuk perintah python manage.py migrate bekerja, pengguna basisdata Oracle anda harus mempunyai hak istimewa untuk menjalankan perintah berikut:

  • CREATE TABLE
  • CREATE SEQUENCE
  • CREATE PROCEDURE
  • CREATE TRIGGER

Untuk menjalankan deretan percobaan proyek, pengguna biasanya butuh hak tambahan ini:

  • 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

Selagi peran RESOURCE mempunyai hak istimewa yang diwajibkan CREATE TABLE, CREATE SEQUENCE, CREATE PROCEDURE, dan CREATE TRIGGER`, dan seorang pengguna diberikan ``RESOURCE WITH ADMIN OPTION dapat memberikan RESOURCE, pengguna seperti itu tidak dapat memberikan hak istimewa sendiri (yaitu CREATE TABLE), dan demikian RESOURCE WITH ADMIN OPTION tidak biasanya cukup untuk menjalankan percobaan.

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.

Semua hak iswimewa ini disertakan dalam peran DBA, yang sesuai untuk digunakan pada basisdata pengembang pribadi.

Backend basisdata Oracle menggunakan paket SYS.DBMS_LOB dan SYS.DBMS_RANDOM, jadi pengguna anda akan membutuhkan menjalankan perizinan padanya. Itu secara biasa dapat diakses ke semua pengguna secara awal, tetapi di kasus itu tidak, anda akan butuh memberikan perizinan seperti itu:

GRANT EXECUTE ON SYS.DBMS_LOB TO user;
GRANT EXECUTE ON SYS.DBMS_RANDOM TO user;

Menyambung ke basisdata

Untuk menghubungkan menggunakan nama layanan dari basisdata Oracle anda, berkas settings.py anda harus terlihat seperti ini:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': 'xe',
        'USER': 'a_user',
        'PASSWORD': 'a_password',
        'HOST': '',
        'PORT': '',
    }
}

Dalam kasus ini, anda harus meninggakan kedua HOST dan PORT kosong. Bagaimanapun, jika anda tidak menggunakan berkas tnsnames.ora atau metode penamaan mirip dan ingin berhubungan menggunakan SID ("xe" dalam contoh ini), kemudian isi kedua HOST dan PORT seperti itu:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': 'xe',
        'USER': 'a_user',
        'PASSWORD': 'a_password',
        'HOST': 'dbprod01ned.mycompany.com',
        'PORT': '1540',
    }
}

Anda harus salah andara mendukung kedua HOST and PORT, atau meninggalkan kedua sebagai string kosong. Django akan menggunakan deskriptor hubungan berbeda tergantung pada pilihan itu.

DSN dan Easy Connect penuh

Sebuah Full DSN atau string Easy Connect dapat digunakan dalam NAME jika kedua HOST dan PORT adalah kosong. Bentuk ini diwajibkan ketika menggunakan RAC atau basisdata tertanam tanpa tnsnames.ora, sebagai contoh.

Contoh dari Easy Connect string:

'NAME': 'localhost:1521/orclpdb1',

Contoh dari string DSN penuh:

'NAME': (
    '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))'
    '(CONNECT_DATA=(SERVICE_NAME=orclpdb1)))'
),

Pilihan urutan

Jika anda berencana menjalankan Django dalam lingkungan banyak antrian (yaitu Apache menggunakan modul MPM awalan pada sistem operasi modern apapun), kemudian anda harus mensetel pilihan threaded dari konfigurasi basisdata Oracle anda menjadi True:

'OPTIONS': {
    'threaded': True,
},

Kegagalam melakukan ini akan menyebabkan tabrakan dan perilaku ganjil lain.

INSERT ... RETURNING INTO

Secara awalan, backend Oracle menggunakan klausa RETURNING INTO untuk efesian mengambil nilai dari AutoField ketika memasukkan baris baru. Perilaku ini mungkin menghasilkan sebuah DatabaseError dallam pengaturan tidak biasa tertentu, seperti ketika memasukkan kedalam tabel jauh, atau kedalam sebuah tampilan dengan sebuah pemicu INSTEAD OF. Klausa RETURNING INTO dapat ditiadakan dengan mengatur pilihan use_returning_into dari konfigurasi basisdata menjadi False:

'OPTIONS': {
    'use_returning_into': False,
},

Dalam kasus ini, backend Oracle akan menggunakan permintaan SELECT terpisah untuk mengambil nilai-nilai AutoField.

Masalah penamaan

Oracle memaksakan batasan panjang nama dari 30 karakter. Untuk mengakomodasi ini, backend memotong penciri basisdata agar cocok, mengganti empat karakter akhir dari nama terpotong dengan sebuah nilai campuran MD5 berulang. Sebagai tambahan, backend merubah penciri basisdata menjadi semua-huruf-besar.

Untuk mencegah perubahan ini (ini biasanya hanya membutuhkan ketika berhubungan dengan basisdata warisan atau mengakses tabel-tabel yang milik pengguna lain), gunakan sebuah nama terkutip sebagai nilai untuk 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"'

Nama terkutip dapat juga digunakan dengan backend basisdata didukung lain Django; kecuali untuk Oracle, bagaimanapun, kutipan tidak mempunyai pengaruh.

Ketika menjalankan migrate, sebuah kesalahan ORA-06552 mungkin ditemui jika kata kunci Oracle tertentu digunakan sebagai nama dari sebuah bidang model atau nilai dari sebuah pilihan db_column. Django mengutip semua penciri digunakan dalam permintaan untuk mencegah kebanyakan masalah seperti itu, tetapi kesalahan ini dapat masih muncul ketika sebuah jenis data oracle digunakan sebagai sebuah nama kolom. Khususnya, hati-hati menghindari penggunaan nama-nama date, timestamp, number atau float sebagai nama bidang.

String NULL dan kosong

Django umumnya memilih menggunakan string kosong ('') daripada NULL, tetapi Oracle memperlakukan keduanya mirip. Untuk menyiasati ini, backend Oracle mengabaikan pilihan null tersirat pada bidang yang mempunyai string kosong sebagai nilai kemungkinan dan membangkitkan DDL seolah-olah null=True. Ketika mengambil dari basisdata, itu dianggap bahwa sebuah nilai NULL dalam satu dari bidang-bidang ini sangat berarti string kosong, dan data secara diam dirubah untuk mencerminkan anggapan ini.

Batasan TextField

Backend Oracle menyimpan TextFields sebagai kolom NCLOB. Oracle memaksakan beberapa pembatasan pada penggunaan seperti kolom LOB secara umum:

  • Kolom LOB tidak boleh digunakan sebagai primary key.
  • Kolom LOB tidak boleh digunakan sebagai indeks.
  • Kolom LOB mugnkin tidak digunakan dalam daftar SELECT DISTINCT. Ini berarti bahwa mencoba menggunakan metode QuerySet.distinct pada sebuah model yang menyertakan kolom TextField akan menghasilkan dalam sebuah kesalahan ORA-00932 ketika berjalan terhadap Oracle. Sebagai pemecahannya, gunakan metode QuerySet.defer dalam berhubungan dengan distinct() untuk mencegah kolom TextField dari menjadi disertakan dalam daftar SELECT DISTINCT.

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:

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 DATABASE-ENGINE in your settings.py file:

DATABASES = {
    'default': {
        'ENGINE': 'mydbengine',
        ...
    },
}

You can see the current list of database engines by looking in django/db/backends.

Menggunakan backend basisdata pihak ketiga

Sebagai tambahan pada basisdata didukung resmi, ada backend disediakan oleh pihak ketiga yang mengizinkan anda menggunakan basisdata lain dengan Django:

Versi Django dan fitur ORM didukung oleh backend tidak resmi sangat beragam. Permintaan mengenai kemampuan khusus dari backend tidak resmi ini, bersama dengan permintaan didukung apapun, harus diarahkan ke saluran pendukung disediakan oleh proyek pihak ke3.

Back to Top