Basisdata¶
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.
Nilai awalan adalah 0
, mempertahankan riwayat perilaku dari menutup hubungan basisdata pada akhir dari setiap permintaan. untuk mengadakan hubungan tetap, setel CONN_MAX_AGE
menjadi sebuah angka positif dari detik. Untuk hubungan tetap tidak terbatas, setel itu menjadi 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 mendukung PostgreSQL 9.4 dan lebih tinggi. psycopg2 2.5.4 atau lebih tinggi dibutuhkan, meskipun terbitan terakhir dianjurkan.
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'
ketikaUSE_TZ
adalahTrue
, nilaiTIME_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¶
Menggunakan pengumpul hubungan dalam suasana transaksi pengumpulan (yaitu pgBouncer) membutuhkan meniadakan kursor sisi-peladen untuk hubungan itu.
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.
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.7 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:
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'
atau None
menggunakan tingkatan terpencil dikonfigurasi peladen. Bagaimanapun, Django bekerja terbaik dengan dan awalan untuk membaca berkomitmen daripada awalan MySQL, pembacaan berulang. Kehilangan data memungkinkan dengan pembacaan berulang.
Dalam versi terlama, backend basisdata MySQL awalan untuk menggunakan tingkat terpencil basisdata (yang awalan untuk membaca berulang) daripada membaca dikomitmen.
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 tidak mendukung pilihan NOWAIT
, SKIP LOCKED
, dan OF
pada pernyataan SELECT ... FOR UPDATE
. Jika select_for_update()
digunakan dengan nowait=True
, skip_locked=True
, atau of
kemudian sebuah NotSupportedError
dimunculkan.
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.7.15 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.
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, # ... }
Mereka akan cukup membuat SQLite menunggu sedikit lama sebelum melemparkan kesalahan "basisdata dikunci"; itu tidak akan melakukan apapun untuk menyelesaikan mereka.
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.
Catatan Oracle¶
Django mendukung Oracle Database Server versi 12.1 dan lebih tinggi. Versi 5.2 atau lebih tinggi dari pengendali Puthon cx_Oracle dibutuhkan.
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.
Beberapa deretan percobaan juga membuat tampilan; untuk menjalankan ini, pengguna juga butuh hak istimewa CREATE VIEW WITH ADMIN OPTION
. Khususnya, ini diperlukan untuk deretan percobaan Django sendiri.
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 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.
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.
- LOB columns may not be used in a
SELECT DISTINCT
list. This means that attempting to use theQuerySet.distinct
method on a model that includesTextField
columns will result in anORA-00932
error when run against Oracle. As a workaround, use theQuerySet.defer
method in conjunction withdistinct()
to preventTextField
columns from being included in theSELECT DISTINCT
list.
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:
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.