Catatan
Dipersembahkan kepada Malcolm Tredinnick
Pada 17 Maret 2013, proyek Django dan komunitas perangkat lunak bebas kehilangan teman dan pengembang.
Malcom adalah pembantu lama pada Django, sebuah model anggota komunitas, pikiran cemerlang, dan seorang teman. Bantuannya pada Django - dan ke banyak proyek sumber terbuka lainnya - hampir tidak mungkin menghitung. Banyak pada tim Django inti mempunyai tambalan pertama mereka ditinjau oleh dia; bimbingannya memperkaya kami. Pertimbangan dia, kesabaran, dan pengabdian akan selalu menjadi inspirasi untuk kami.
Terbitan Django ini untuk Malcolm.
-- Pengembang Django
November 6, 2013
Selamat datang di Django 1.6!
Catatan terbitan ini mencangkupi new features, sama halnya beberapa backwards incompatible changes anda akan ingin menjadi waspada ketika meningkatkan dari Django 1.5 atau versi terlama. Kami telah membuang beberapa fitur, yang rinciannya di our deprecation plan, dan kami telah begun the deprecation process for some features.
Django 1.6, seperti Django 1.5, membutuhkan Python 2.6.5 atau diatasnya. Python 3 juga secara resmi didukung. Kami sangat menganjurkan terbitan kecil terakhir untuk setiap rangkaian Python yang didukung (2.6.X, 2.7.X, 3.2.X, and 3.3.X).
Django 1.6 akan menjadi rangkaian terbitan terakhir untuk mendukung Python 2.6; dimulai dengan Django 1.7, minimal dukungan versi Python akan menjadi 2.7.
Python 3.4 tidak didukung, tetapi dukungan akan ditambahkan di Django 1.7.
Cetakan awalan digunakan oleh startproject
dan startapp
telah disederhanakan dan dimodernisasikan. admin sekarng diadakan secara awalan di proyek baru; kerangka kerja sites tidak lagi. clickjacking prevention sekarang di dan awalan basisdata pada SQLite.
Jika awalan cetakan tidak cocok dengan rasa anda, anda dapat menggunakan custom project and app templates.
Pengelolaan transaksi Django dirombak. Tingkat-basisdata pembenaran otomatis sekarang nyala sebagai awalan. Ini membuat penanganan transaksi lebih jelas dan harus meningkatkan penampilan. API yang ada diusangkan, dan API baru telah diperkenalkan, sebagai digambarkan di transaction management docs.
Django sekarang menggunakan penggunaan kembali hubungan basisdata sama untuk beberapa permintaan. Ini menghindari kelebihan dari membangun kembali sebuah hubungan pada awal dari setiap permintaan. Untuk kesesuaian kebelakang, fitur ini ditiadakan secara awalan. Lihat Hubungan tetap untuk rincian.
Django 1.6 dibekali dengan pejalan percobaan baru yang mengizinkan lebih keluwesan di tempat dari percobaan. Pejalan sebelumnya (django.test.simple.DjangoTestSuiteRunner
) menemukan percobaan hanya di modul models.py
dan tests.py
dari paket Python di INSTALLED_APPS
.
Pejalan baru (django.test.runner.DiscoverRunner
) menggunakan fitur penemuan percobaan dibangun kedalam unittest2
(versi dari unittest
di pustaka standar Python 2.7+, dan digabung dengan Django). Dengan penemuan percobaan, percobaan dapat ditempatkan di tiap modul yang namanya cocok dengan pola test*.py
.
Sebagai tambahan, label percobaan disediakan pada ./manage.py test
untuk menunjuk percobaan khusus untuk berjalan harus sekarang menjadi jalur bertitik Python penuh (atau jalur direktori), daripada halur-semu applabel.TestCase.test_method_name
. Ini mengizinkan menjalankan percobaan ditempatkan dimana saja di basis kode anda, daripada hanya di INSTALLED_APPS
. Untuk rincian lebih, lihat Percobaan di Django.
Perubahan ini adalah kesesuaian-kebelakang; lihat backwards-incompatibility notes.
Dukungan untuk time zones diperkenalkan di DJango 1.4 tidak bekerja baik dengan QuerySet.dates()
: pengumpulan selalu dilakukan di UTC. Batasan ini telah diangkat di Django 1.6. Gunakan QuerySet.datetimes() <django.db.models.query.QuerySet.datetimes>`untuk melakukan mengetahui pengumpulan zona waktu di :class:`~django.db.models.DateTimeField()
.
Django 1.6 menambahkan dukungan untuk savepoint di SQLite, dengan beberapa limitations.
BinaryField
¶Bidang model django.db.models.BinaryField
baru mengizinkan penyimpanan dari data biner mentah di basisdata.
GeoDjango sekarang menyediakan form fields and widgets untuk bidang khusus-geo nya. Mereka adalah berdasarkan-OpenLayer secara awalan, tetapi mereka dapat disesuaiakan untuk menggunakan apapun kerangka kerja JS lain.
check
ditambahkan untuk mengecek kesesuaian¶Sebuah perintah pengelolaan check
telah ditambahkan, mengadakan anda untuk memeriksa jika konfigurasi anda saat ini (saat ini bertujuan pada pengaturan) adalah cocok dengan versi saat ini dari Django.
Model.save()
berubah¶Metode Model.save()
sekarang mencoba secara langsung UPDATE
basisdata jika instance mempunyai sebuah nilai primary key. Sebelumnya SELECT
telah dilakukan untuk menentukan jika UPDATE
atau INSERT
dibutuhkan. Algoritma baru dibutuhkan jika hanya satu permintaan untuk memperbaharui baris yang ada selagi algoritma lama membutuhkan dua. Lihat Model.save()
untuk lebih rinci.
Di beberapa kasus yang jarang basisdata tidak melaporkan bahwa sebuah baris yang cocok telah ditemukan ketika melakukan sebuah UPDATE
. Sebuah contoh adalah pemicu ON UPDATE
PostgreSQL yang mengembalikan NULL
. Dalam kasus tersebut itu memungkinkan menyetel bendera django.db.models.Options.select_on_save
untuk memaksa menyimpan menggunakan algoritma lama.
PermissionDenied
untuk segera menggagalkan rantai otentifikasi.HttpOnly
dapat disetel di kue CSRF dengan CSRF_COOKIE_HTTPONLY
.assertQuerysetEqual()
sekarang diperiksa untuk urutan tidak ditentukan dan memunculkan ValueError
jika urutan tidak ditentukan dilihat. Urutan dilihat sebagai tidak ditentukan jika QuerySet
diberikan tidak diurutkan dan ada lebih dari satu nilai terurut untuk dibandingkan.earliest()
untuk simetri dengan latest()
.year
, month
dan day
, ORM sekarang mendukung pencarian hour
, minute
dan second
.EmailField
, URLField
, IntegerField
, FloatField
dan DecimalField
menggunakan atribut jenis baru tersedia di HTML5 (type='email'
, type='url'
, type='number'
). Catat bagwa karena dukungan tak menentu dari jenis masukan number
dengan angka lokal di peramban saat ini, Django hanya menggunakannya ketika bidang numerik tidak di lokalkan.number
untuk lazy plural translations dapat disediakan pada waktu terjemahan daripada saat waktu penentuan.BaseCommand.can_import_settings
sekarang dilakukan berdiri sendiri dari menangani dari lokal yang harus aktif selama penjalanan dari perintah. Terakhir dapat sekarang dipengaruhi dengan pilihan internal leave_locale_alone
baru. Lihat Pengelolaan perintah dan lokal untuk lebih rinci.success_url
dari DeletionMixin
sekarang ditambahkan dengan __dict__
object
nya.HttpResponseRedirect
dan HttpResponsePermanentRedirect
sekarang menyediakan sebuah atribut url
(setara dengan tanggapan URL akan dialihkan).MemcachedCache
sekarang menggunakan protokol pickle
yang terakhir tersedia.SuccessMessageMixin
yang menyediakan sebuah atribut success_message
untuk FormView
berdasarkan kelas-kelas.django.db.models.ForeignKey.db_constraint
dan django.db.models.ManyToManyField.db_constraint
.django.contrib.syndication
) sekarang dapat melewatkan konteks tambahan melalui cetakan umpan menggunakan callback Feed.get_context_data()
baru.column-<field_name>
di HTML jadi kepalakolom dapat digaya dengan CSS, sebagai contoh untuk menyetel lebar kolom.blocktrans
sekarang mematuhi TEMPLATE_STRING_IF_INVALID
untuk variabel tidak hadir di konteks, sama seprti penyusunan cetakan lain.SimpleLazyObject
sekarang akan menghadirkan gambaran lebih membantu dalam keadaan mencari kesalahan shell.GeometryField
is now editable
with the OpenLayers widget in the admin.diffsettings
mendapatkan pilihan --all
.django.forms.fields.Field.__init__
sekarang memanggil super()
, mengizinkan campuran bidang untuk menerapkan metode __init__()
yang akan dapat dihandalkan dipanggil.validate_max
telah ditambahkan ke BaseFormSet
dan formset_factory()
, dan ModelForm
dan versi berderet dari yang sama. Perilaku dari pengesahan untuk formset dengan max_num
telah dijelaskan. Sebelumnya perilaku tidak terdokumentasi yang mengeraskan formset terhadap serangan kelelahan ingatan telah didokumentasikan, dan tidak terdokumentasi terbatas dari lebih tinggi 1000 atau max_num
formulir telah dirubah jadi itu selalu 1000 lebih daripada max_num
.BCryptSHA256PasswordHasher
untuk menyelesaikan masalah pemotongan sandi dengan bcrypt.ModelForm
menerima beberapa pilihan Meta
baru.localized_fields
akan dilokalkan (dengan menyetel localize
pada bidang formulir).labels
, help_texts
dan error_messages
mungkin digunakan untuk menyesuaikan bidang awalan, lihat Mengesampingan nilai awal untuk rincian.choices
pada bidang model sekarang menerima sebuah perulangan dari perulangan sebagai gantinya membutuhkan sebuah perulangan dari daftar atau tuple.reason_phrase
.logout()
, password_reset()
, password_reset_confirm()
, dan password_change()
, anda dapat sekarang melewati nama URL dan mereka akan diselesaikan.dumpdata --pks
baru menentukan primary key dari obyek untuk membuang. Pilihan ini dapat hanya digunakan dengan satu model.QuerySet
first()
dan last()
yang metode kenyamanan mengembalikan obyek pertama atau terakhir mencocokkan saringan. Mengembalikan None
jika tidak ada pencocokan obyek.View
dan RedirectView
sekarang mendukung metode HTTP PATCH
.GenericForeignKey
sekarang mengambil sebuah pilihan argumen for_concrete_model
, yang ketika disetel ke False
mengizinkan bidang untuk mengacu model proxy. Awalan adalah True
untuk memelihara perilaku lama.LocaleMiddleware
sekarang menyimpan bahasa aktif di sesi jika itu tidak hadir disana. Ini mencegah kehilangan dari pengaturan bahasa setelah menyiram sesi, sebagai contoh keluar.SuspiciousOperation
telah dibedakan menjadi sejumlah subkelas, dan setiap akan masuk untuk mencocokan pencatat bernama dibawah hirarki pencatatan django.security
. Bersama dengan perubahan ini, sebuah mekanisme handler400
dan tampilan awal digunakan ketika kapanpun SuspiciousOperation
mencapai penangan WSGI untuk mengembalikan sebuah HttpResponseBadRequest
.DoesNotExist
sekarang menyertakan sebuah pesan yang menunjukkan nama dari atribut digunakan untuk pencarian.get_or_create()
tidak lagi membutuhkan setidaknya satu argumen katakunci.SimpleTestCase
termasuk pembantu tuntutan baru untuk percobaan kesalahan formset: assertFormsetError()
.QuerySet
oleh select_related()
dapat dibersihkan menggunakan select_related(None)
.get_extra()
dan get_max_num()
pada InlineModelAdmin
mungkin dikesampingkan untuk menyesuaikan jumlah tambahan dan maksimal dari formulir berderet.total_error_count()
.ModelForm
sekarang dapat menimpa pesan-pesan kesalahan ditentukan di bidang model dengan menggunakan argumen error_messages
dari pembangun Field
. Untuk mengambil kesimpulan dari fitur ini dengan bidang penyesuaian anda, see the updated recommendation untuk memunculkan ValidationError
.ModelAdmin
sekarang mempertahankan penyaring pada daftar tampilan setelah membuat, menyunting atau menghapus sebuah obyek. Itu memungkinkan menyimpan kembali perilaku sebelumnya dari membersihkan penyaring dengan mengatur atribut preserve_filters
menjadi False
.FormMixin.get_prefix
(yang mengembalikan FormMixin.prefix
secara awalan) untuk mengizinkan menyesuaikan prefix
dari formulir.Manager.raw()
atau cursor.execute()
) sekarang dapat menggunakan gaya parameter "pyformat", dimana placeholder dalam permintaan diberikan sebagai '%(name)s'
dan parameter dilewatkan sebagai sebuah kamus daripada sebuah daftar (kecuali di SQLite). Ini telam lama mungkin (tetapi bukan secara resmi didukung) di MySQL dan PostgreSQL, dan sekarang juga tersedia di Oracle.django.contrib.auth.hashers.PBKDF2PasswordHasher
untuk merubah nilai awal. Sandi will be upgraded untuk menggunakan perhitungan putaran baru sesuai kebutuhan.Peringatan
Sebagai tambahan pada perubahan diuraikan di bagian ini, pastikan untuk meninjau kembali deprecation plan untuk setiap fitur yang telah dipindahkan. Jika anda belum memperbaharui kode anda dalam linimasa pengusangan untuk fitur yang diberikan, perpindahannya mugkin muncul sebagai perubahan ketidaksesuaian kebelakang.
Pembenaran otomatis tingkat-basisdata diadakan secara awalan di Django 1.6. Selagi ini tidak merubah jiwa umum dari pengelolaan transaksi Django, ada sedikit ketidaksesuaian-kebelakang.
assertNumQueries
¶Perubahan di pengelolaan transaksi dapat menghasilkan di pernyataan tambahan untuk membuat, menerbitkan atau menyimpan kembali titik penyimpanan sampai terbitan ini.
Jika percobaan menggunakan assertNumQueries()
gagal karena dari angka tertinggi dari permintaan daripada diharapkan, periksa bahwa permintaan tambahan dikaitkan ke titik penyimpanan, dan menyesuaikan angka yang diharapkan dari permintaan sesuai dengan itu.
Di versi sebelumnya, perbaikan otomatis tingkatan-basisdata hanya sebuah pilihan untuk PostgreSQL, dan itu ditiadakan secara awalan. Pilihan ini sekarang diabaikan dan dapat dipindah.
Untuk merawat ketetapan lebih hebat dengan modul unittest Python, pejalan percobaan baru (django.test.runner.DiscoverRunner
) tidak secara otomatis mendukung beberapa jenis dari percobaan yang telah didukung oleh pejalan sebelumnya:
models.py
dan tests/__init__.py
tidak lagi ditemukan dan berjalan. Pindahkan mereka ke sebuah berkas yang namanya dimulai dengan test
.Django menggabungkan versi dirubah dari modul doctest
dari pustaka standar Python (di django.test._doctest
) dan menyertakan beberapa kegunaan doctest tambahan. Kegunaan ini diusangkan dan akan dipindahkan di Django 1.8; deretan doctest harus diperbaharui untuk bekerja dengan modul doctest pustaka standar (atau dirubah ke percobaan unittest-sesuai).
Jika anda berharap menunda perbaharuan ke deretan percobaan anda, anda dapat menyetel pengaturan TEST_RUNNER
anda menjadi django.test.simple.DjangoTestSuiteRunner
untuk sepenuhnya menyimpan kembali perilaku percobaan lama. DjangoTestSuiteRunner
diusangkan tetapi tidak akan dipindahkan dari Django sampai versi 1.8.
django.contrib.gis.tests.GeoDjangoTestSuiteRunner
¶Ini adalah untuk pengembang yang bekerja pada aplikasi GeoDjango itu sendiri dan terkait ke barang diatas tentang perubahan di penjalan percobaan:
Penjalan percobaan django.contrib.gis.tests.GeoDjangoTestSuiteRunner
telah dipindahkan dan setelan pengerjaan percobaan GeoDajngo berdiri sendiri itu terapkan tidak didukung lagi. Untuk menjalankan percobaan GeoDjango cukup gunakan DiscoverRunner
baru dan tentukan aplikasi django.contrib.gis
.
Perkenalan dari pejalan percobaan baru juga sedikit merubah cara dimana model percobaan diimpor. Sebagai hasilnya, percobaan apapun yang menimpa AUTH_USER_MODEL
untuk mencoba perilaku dengan satu dari model pengguna percobaan Dajngo ( django.contrib.auth.tests.custom_user.CustomUser
dan django.contrib.auth.tests.custom_user.ExtensionUser
) harus sekarang secara eksplisit impor model User di modul percobaan anda:
from django.contrib.auth.tests.custom_user import CustomUser
@override_settings(AUTH_USER_MODEL='auth.CustomUser')
class CustomUserFeatureTests(TestCase):
def test_something(self):
# Test code here ...
Impor ini memaksa model pengguna penyesuaian untuk didaftarkan. Tanpa impor ini, percobaan akan tidak dapat bertukar di model pengguna penyesuaian, dan anda akan mendapatkan sebuah pelaporan kesalahan:
ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.CustomUser' that has not been installed
day
, month
, dan week_day
¶Django 1.6 memperkenalkan dukungan zona waktu untuk pencarian day
, month
, dan week_day
ketika USE_TZ
adalah True
. Pencarian ini sebelumnya dilakukan di UTC tanpa memperhatikan dari zona waktu sekarang.
Ini membutuhkan time zone definitions in the database. Jika anda sedang menggunakan SQLite, anda harus memasang pytz. Jika anda sedang menggunakan MySQL, anda harus memasang pytz dan memuat tabel zona waktu dengan mysql_tzinfo_to_sql.
QuerySet.datetimes()
¶Ketika time zone support ditambahkan di Django 1.4 telah aktif, pencarian QuerySet.dates()
mengembalikan hasil tidak diharapkan, karena pengumpulan telah dilakukan dalam UTC. Untuk memperbaiki ini, Django 1.6 memperkenalkan API baru, QuerySet.datetimes()
. Ini membutuhkan sedikit perubahan di kode anda.
QuerySet.dates()
mengembalikan obyek date
¶QuerySet.dates()
sekarang mengemblikan sebuah daftar dari date
. Itu digunakan untuk mengembalikan sebuah daftar datetime
.
QuerySet.datetimes()
mengembalikan sebuah daftar dari datetime
.
QuerySet.dates()
tidak lagi digunakan pada DateTimeField
¶QuerySet.dates()
memunculkan sebuah kesalahan jika itu digunakan di DateTimeField
ketika dukungan zona waktu aktif. Gunakan QuerySet.datetimes()
sebagai gantinya.
date_hierarchy
membutuhkan penentuan zona waktu¶Fitur date_hierarchy
dari admin sekarang bergantung pada QuerySet.datetimes()
ketika itu digunakan di DateTimeField
.
Ini membutuhkan penentuan zona waktu di basisdata ketika USE_TZ
adalah True
. Learn more.
date_list
dalam tampilan umum membutuhkan penentuan zona waktu¶Untuk alasan sama, mengakses date_list
di konteks dari tampilan umum berdasarkan-tanggal membutuhkan penentuan zona waktu di basisdata ketika tampilan berdasarkan pada DateTimeField
dan USE_TZ
adalah True
. Learn more.
Django 1.6 memperkenalkan pencarian hour
, minute
, dan second
di DateTimeField
. Jika anda mempunyai bidang model dipanggil hour
, minute
, atau second
, pencarian baru akan bentrok dengan nama bidang anda. Tambahkan sebuah pencarian exact
jelas jika ini adalah sebuah masalah.
BooleanField
tidak lagi disetel ke False`¶Ketika sebuah BooleanField
tidak mempunyai default
jelas, nilai awalan tersirat adalah None
. Dalam versi sebelumnya dari Django, itu adalah False
, tetapi itu tidak mewakili secara akurat kekurangan dari sebuah nilai.
Kode yang bergantung pada nilai awalan menjadi False
mungkin memunculkan sebuah pengecualian ketika menyimpan instance model baru ke basisdata, karena None
bukan sebuah nilai yang dapat diterima untuk sebuah BooleanField
. Anda harus juga menentukan default=False
di penentuan bidang, atau memastikan bidang disetel ke True
atau False
sebelum menyimpan obyek.
Pengeluaran dari harfiah dapat diterjemahkan dari cetakan dengan perintah makemessages
sekarang dengan benar mengenali gagasan i18n ketika mereka ditempatkan setelah sebuah {#
/ #}
- ketik komentar di baris sama. Sebagai contoh:
{# A comment #}{% trans "This literal was incorrectly ignored. Not anymore" %}
Komentar untuk penterjemah dalam cetakan ditentukan menggunakan {#
/ #}
harus pada akhir dari sebuah baris. Jika mereka tidak, komentar diabaikan dan makemessages
akan membangkitkan sebuah peringatan. Sebagai contoh:
{# Translators: This is ignored #}{% trans "Translate me" %}
{{ title }}{# Translators: Extracted and associated with 'Welcome' below #}
<h1>{% trans "Welcome" %}</h1>
reverse()
¶Ketika membalikkan URL, Django tidak memberlakukan urlquote()
pada argumen sebelum menambahkan mereka di pola URL. Kesalahan ini diperbaiki di Django 1.6. Jika anda bekerja dengan kesalahan ini dengan menerapkan URL mengutip sebelum melewatkan argumen pada reverse()
, ini mungkin menghasilkan dalam kutip-ganda. Jika ini terjadi, cukup pindahkan URL mengutip dari kode anda. Anda akan juga harus mengganti karakter khusus di URL digunakan dalam assertRedirects()
dengan versi tersandi mereka.
Aplikasi komentar sekarang menggunakan sebuah GenericIPAddressField
untuk menyimpan alamat IP komentar, untuk mendukung komentar diajukan dari alamat IPv6. Sampai sekarang, itu menyimpan mereka di sebuah IPAddressField
, yang hanya berarti mendukung IPv4. Ketika menyimpan sebuah komentar yang dibuat dari alamat IPv6, alamat akan secara diam dipotong di basisdata MySQL, dan memunculkan sebuah pengecualian di Oracle. Anda akan butuh merubah jenis kolom di basisdata anda untuk mengambil keuntungan dari perubahan ini.
Untuk MySQL, jalankan permintaan ini di basisdata proyek anda:
ALTER TABLE django_comments MODIFY ip_address VARCHAR(39);
Untuk Oracle, jalankan permintaan ini:
ALTER TABLE DJANGO_COMMENTS MODIFY (ip_address VARCHAR2(39));
Jika anda tidak memberlakukan perubahan ini, perilaku tidak berubah: di MySQL, alamat IPv6 secara diam dipotong; di Oracle, sebuah pengecualian dibangkitkan. Tidak ada perubahan basisdata dibutuhkan untuk basisdata SQLite atau PostgreSQL.
cursor.execute
¶Ketika anda sedang menjalankan permintaan SQL mentah melalui metode cursor.execute, aturan mengenai hardiah persen ganda (%
) didalam permintaan telah kompak. Perilaku lama bergantung di backend basisdata. Sekarang, lintas semua backend, anda hanya butuh menggandakan karakter persen harfiah jika anda sedang juga menyediakan parameter pengganti. Sebagai contoh:
# No parameters, no percent doubling
cursor.execute("SELECT foo FROM bar WHERE baz = '30%'")
# Parameters passed, non-placeholders have to be doubled
cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' and id = %s", [self.id])
Pengguna SQLite
butuh memeriksa dan memperbaharui permintaan tersebut.
Membangun HTML dari bidang formulir model sesuai pada bidang model ManyToManyField
digunakan untuk mendapatkan kalimat kode-keras:
Tekan "Control", atau "Command" pada Mac, untuk memilih lebih dari satu.
(atau terjemahannya pada lokal aktif) dikenakan sebagai bantuan lagenda ditampilkan bersama mereka jika tak ada model
maupun form
atribut help_text
telah ditentukan oleh pengguna (atau string ini telah ditambahkan ke setiap help_text
yang telah disediakan).
Sejak ini terjadi di lapisan model, tidak ada cara mencegah teks dari muncul di kasus-kasus domana itu tidak berlaku seperti bidang formulir yang menerapkan interaksi pengguna yang anda tidak melibatkan papan kunci dan/atau sebuah tetikus.
Dimulai dengan Django 1.6, sebagai sebuah ketentuan kesesuaian-kebelakang sementara ad-hoc, logika untuk menambahkan kalimat "Hold down..." telah dipindahkan ke lapisan bidang formulir model dan dirubah untuk menambahkan hanya teks ketika widget terkait adalah SelectMultiple
atau subkelas terpilih.
Perubahan ini dapat mempengaruhi anda di cara ketidaksesuaian kebelakang jika anda menggunakan bidang formulir model penyesuaian dan/atau widget untuk bidang model ManyToManyField
yang UI nya bergantung pada ketentuan otomatis dari kalimat kode-kerasyang disebutkan. Penerapan bidang formulir ini butuh menyesuaikan ke skenario baru dengan menyediakan penanganan milik mereka dari atribut help_text
.
Apliaksi yang menggunakan fasilitas model form Django bersama-sama dengan formulir siap-pakai Django fields dan widgets tidak terpengaruh tetapi butuh disadari dari apa digambarkan dalam Mung dari teks bantuan dari bidang formulir model untuk bidang-bidang ManyToManyField dibawah.
Perulangan QuerySet
telah berubah untuk segera merubah semua baris yang diambil pada obyek Model
. Di Django 1.5 dan lebih awal untuk mengambil baris telah dirubah ke obyek Model
dalam 100 potongan.
Kode yang ada akan bekerja, tetapi sejumlah baris dirubah ke obyek mungkin berubah dalam kasus penggunaan tertentu. Penggunaan seperti itu termasuk sebagian berulang terhadap sebuah queryset atau penggunaan apapun yang mengakhiri melakukan __bool__
atau __contains__
.
Terutama kebanyakan backend basisdata melakukan pengambilan semua baris dalam satu pergi sudah di 1.5.
Itu masih memungkinkan merubah barisan diambil pada obyek Model
lazily dengan menggunakan metode iterator()
.
BoundField.label_tag
sekarang menyertakan label_suffix
formulir¶Ini adalah konsisten dengan bagaimana metode seperti Form.as_p
dan Form.as_ul
membangun label.
Jika anda secara manual membangun label_tag
dalam cetakan anda:
{{ form.my_field.label_tag }}: {{ form.my_field }}
anda akan ingin memindahkan titik dua (atau apapun pemisah lainnya anda mungkin gunakan) untuk menghindari penggandaan itu ketika meningkatkan ke Django 1.6. Cetakan berikut di Django 1.6 akan membangun secara mirip ke cetakan diatas di Django 1.5, kecuali bahwa titik koma akan muncul didalam unsur <label>
.
{{ form.my_field.label_tag }} {{ form.my_field }}
akan membangun sesuatu seperti:
<label for="id_my_field">My Field:</label> <input id="id_my_field" type="text" name="my_field" />
Jika anda ingin menjaga perilaku saat ini dari membangun label_tag
tanpa label_suffix
, instatiate formulir label_suffix=''
. Anda dapat juga menyesuaikan label_suffix
di berdasarkan per-bidang menggunakan parameter label_suffix
baru di label_tag()
.
_changelist_filters
¶Untuk mencapai melindungi dan meyimpan kembali daftar tampilan penyaring, tampilan admin sekarang melewatkan sekitar _changelist_filters parameter GET. Itu adalah penting bahwa akun anda untuk perubahan itu jika anda mempunyai penyesuaian cetakan admin atau jika percobaan anda bergantung pada URL sebelumnya. Jika anda ingin merubah ke perilaku aslinya anda dapat menyetel atribut preserve_filters
menjadi False
.
django.contrib.auth
menggunakan pengkodean berbasis 64 dari PK User
¶Versi lampau dari Django menggunakan penyandian base 36 dari primary key User
di tampilan setel kembali sandi dan URL (django.contrib.auth.views.password_reset_confirm()
). Penyandian base 36 adalah cukup jika perimary key user adalah sebuah integer, bagaimanapun, dengan perkenalan dari penyesuaian model user di Django 1.5, yang anggapan mungkin tidak lagi menjadi benar.
django.contrib.auth.views.password_reset_confirm()
telah dirubah untuk mengambil parameter uidb64
daripada uidb36
. Jika anda membalik tampilan ini, sebagai contoh di penyesuaian cetakan password_reset_email.html
, pastikan untuk memperbaharui kode anda.
Sebuah shim sementara untuk django.contrib.auth.views.password_reset_confirm()
yang akan mengizinkan tautan setel kembali sandi dibangkitkan sebelum Django 1.6 untuk melanjutkan bekerja telah ditambahkan untuk menyediakan kesesuaian kebelakang; ini akan dipindahkan di Django 1.7. Dengan demikian, selama situs anda telah menjalankan Django 1.6 untuk lebih dari PASSWORD_RESET_TIMEOUT_DAYS
, perubahan ini tidak akan mempunyai pengaruh. Jika tidak (sebagai contoh, jika anda meningkatkan secara langsung dari Django 1.5 ke Django 1.7), kemudian apapun tauran setel kembali sandi dibangkitkan sebelum anda meningkatkan ke Django 1.7 atau terakhir tidak akan bekerja setelah peningkatan.
Sebagai tambahan, jika anda mempunyai apapun penyesuaian URL setel kembali sandi, anda akan butuh memperbaharui mereka dengan mengganti uidb36
dengan uidb64
dan tanda garis yang mengikuti pola dengan sebuah garis miring. Juga tambah _\-
ke daftar dari karakter yang mungkin cocok dengan pola uidb64
.
Sebagai contoh:
url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm',
name='password_reset_confirm'),
menjadi:
url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm',
name='password_reset_confirm'),
Anda mungkin juga ingin menambahkan shim untuk mendukung gaya lama tautan setel kembali. Menggunakan contoh diatas, anda akan merubah url yang ada dengan mengganti django.contrib.auth.views.password_reset_confirm
dengan django.contrib.auth.views.password_reset_confirm_uidb36
dan juga memindahkan argumen name
jadi itu tidak bertentangan dengan url baru:
url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm_uidb36'),
Anda dapat memindahkan pola URL ini setelah aplikasi anda telah disebarkan dengan Django 1.6 untuk PASSWORD_RESET_TIMEOUT_DAYS
.
Secara riwayat, django.contrib.sessions
menggunakan pickle
untuk menserialisasikan data sesi sebelum menyimpannya di backend. Jika anda sedang menggunakan signed cookie session backend dan SECRET_KEY
dikenal oleh seorang penyerang (tidak ada kerentanan warisan di Django yang akan menyebabkan itu bocor), penyerang dapat memasukkan sebuah string ke dalam sesi yang, ketika tidak mengawetkan, menjalankan kode berubah-ubah di peladen. Teknik untuk melakukannya adalah sederhana dan mudah tersedia di internet. Meskipun penyimpanan sesi kue menandai data disimpan-kue untuk mencegah rusak, sebuah bocoran SECRET_KEY
segera meningkatkan kerentanan ke pengerjaan kode terpencil.
Serangan ini dapat diredakan dengan menserialkan data sesi menggunakan JSON daripada pickle
. Untuk menfasilitasi ini, Django 1.5.3 memperkenalkan pengaturan baru, SESSION_SERIALIZER
, untuk menyesuaikan bentuk serialisasi sesi. Untuk kesesuaian kebelakang, awalan pengaturan ini menggunakan pickle
di Django 1.5.3, tetapi kami telah merubah awalan ke JSOn di 1.6. Jika anda meningkatkan dan mengganti dari pickle ke JSON, sesi dibuat sebelum peningkatan akan hilang. Selagi serialisasi JSON tidak mendukung semua obyek Python seperti pickle
lakukan, kami sangat menganjurkan menggunakan sesi serialisasi-JSON. Waspada dari berikut ketika memeriksa kode anda untuk menentukan jika serialisasi JSON akan bekerja untuk aplikasi anda:
request.session
.datetime
ke set_expiry()
akan tidak bekerja seperti nilai datetime
adalah tidak dapat serialisasi di JSON. Anda dapat menggunakan nilai integer sebagai gantinya.Lihat dokumentasi Serialisasi sesi untuk lebih rinci.
Django 1.6 mengandung banyak perubahan pada ORM. Perubahan ini dibagi menjadi tiga kategori:
Perubahan ini dapat menghasilkan di beberapa masalah kesesuaian. Sebagai contoh, beberapa permintaan akan sekarang membangkitkan nama lain tabel berbeda. Ini dapat mempengaruhi QuerySet.extra()
. Sebagai tambahan beberapa permintaan akan sekarang membuat hasil berbeda. Sebuah contoh adalah exclude(condition)
dimana kondisi adalah satu rumit (mengacu banyak penyertaan didalam Q objects
). Dalam banyak kasus permintaan yang dipengaruhi tidak membuat hasil di Django 1.5 tetapi melakukan sekarang. Sayangnya ada juga kasus-kasus yang membuat hasil berbeda, tetapi juga tidak Django 1.5 maupun 1.6 membuat hasil benar.
Akhirnya, terdapat banyak perubahan pada API internal ORM.
django.db.models.query.EmptyQuerySet
tidak dapat diinstiasikan lagi - itu adalah hanya berguna sebagai penanda kelas untuk memeriksa jika none()
telah dipanggil: isinstance(qs.none(), EmptyQuerySet)
Jika kode CSS/JavaScript anda digunakan untuk mengakses widget masukan HTML berdasarkan jenis, anda harus meninjau kembali itu seperti widget type='text'
mungkin sekarang mengeluarkan seperti type='email'
, type='url'
atau type='number'
tergantung pada jenis bidang yang sesuai mereka.
error_messages
bidang formulir yang mengandung placeholder harus sekarang selalu menggunakan bernama placeholder("ilai '%(value)' terlalu besar"
daripada "Nilai '%s' terlalu besar"
). Lihat bidang sesuai untuk rincian tentang nama-nama dari placeholder. Perubahan di 1.6 terutama mempengaruhi DecimalField
dan ModelMultipleChoiceField
.
Beberapa error_messages
untuk IntegerField
, EmailField
, IPAddressField
, GenericIPAddressField
, dan SlugField
telah tertindih karena mereka menggandakan pesan kesalahan yang sudah disediakan oleh pengecek diikat ke bidang.
Karena sebuah perubahan di alur kerja pengesahan formulir, metode TypedChoiceField
coerce
harus selalu mengembalikan sebuah nilai hadir di atribut bidang choices
. Batasan tersebut harus diangkat kembali di Django 1.7.
Telah ada perubahan di cara waktu habis ditangani di backend cache. Secara eksplisit melewatkan di timeout=None
tidak lagi mengasilkan di penggunaan awalan waktu habis. itu akan sekarang menyetel waktu habis bukan-kadaluarsa. Melewatkan 0 kedalam backend memcached tidak lagi menggunakan awalan waktu habis, dan sekarang akan menyetel-dan-berakhir-segera nilai.
Aplikasi django.contrib.flatpages
digunakan untuk menyetel kepala HTTP penyesuaian untuk tujuan mencari kesalahan. Kegunaan ini tidak didokumentasikan dan membuat menyembunyikan tidak efektif jadi itu telah dipindahkan, bersama dengan penerapan umumnya, sebelumnya tersedia di django.core.xheaders
.
XViewMiddleware
telah dipindahkan dari django.middleware.doc
ke django.contrib.admindocs.middleware
karena itu adalah sebuah penerapan rincian dari admindoc, terbukti tidak menjadi digunakan kembali secara umum.
GenericIPAddressField
sekarang akan hanya mengizinkan nilai blank
jika nilai null
juga diizinkan. Membuat sebuah GenericIPAddressField
dimana blank
diizinkan tetapi null
tidak akan memicu sebuah kesalahan pengesahan model karena nilai blank
selalu disimpan sebagai null
. Sebelumnya, menyimpan nilai blank
di bidang yang tidak mengizinkan null
akan menyebabkan pengecualian basisdata pada waktu berjalan.
Jika sebuah pengecualian NoReverseMatch
dimunculkan dari sebuah metode ketika membangun sebuah cetakan, itu adalah tidak diam. Sebagai contoh, {{ obj.view_href }}
akan menyebabkan cetakan membangun menjadi gagal jika view_href()
memunculkan NoReverseMatch
. Tidak ada perubahan pada etiket {% url %}
, itu menyebabkan membangun cetakan menjadi gagal seperti selalu ketika NoReverseMatch
dimunculkan.
django.test.Client.logout()
sekarang memanggil django.contrib.auth.logout()
yang akan mengirim sinyal user_logged_out()
.
Authentication views sekarang dibalik berdasarkan nama, ukan tempat mereka di django.contrib.auth.views
. Jika anda sedang menggunakan tampilan tanpa sebuah name
, anda harus memperbaharui urlpatterns
anda untuk menggunakan url()
dengan parameter name
. Sebagai contoh:
(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete')
menjadi:
url(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete', name='password_reset_complete')
RedirectView
sekarang mempunyai atribut pattern_name yang mengizinkannya memilih sasaran dengan membalikkan URL.
Di Django 1.4 dan 1.5, string kosong tidak sengaja dianggap sandi yang sah. Ini berarti set_password()
akan menyimpan sandi kosong sebagai sandi tidak berguna seperti set_unusable_password()
lakukan, dan dengan demikian check_password()
selalu dikembalikan False
untuk sandi kosong. Ini telah diperbaiki di terbitan ini: sandi kosong adalah sekarang sah.
Admin changelist_view
sebelumnya menerima sebuah parameter GET pop
untuk menandakan itu telah ditampilkan di popup. Parameter ini telah dinamai menjadi _popup
untuk tetap konsisten dengan sisa dari tampilan admin. Anda harus memperbaharui cetakan penyesuaian anda jika mereka menggunakan nama parameter sebelumnya.
validate_email()
sekarang menerima alamat surel dengan localhost
sebagai ranah.
Pilihan baru makemessages --keep-pot
mencegah menghapus berkas .pot sementara dibangkitkan sebelum pembuatan berkas .po.
django.core.servers.basehttp.WSGIServerException
yang tidak didokumentasikan telah dipindahkan. Gunakan socket.error
disediakan oleh pustaka standar sebagai gantinya. Perubahan ini juga diterbitkan di Django 1.5.5.
Tanda tangan dari django.views.generic.base.RedirectView.get_redirect_url()
telah berubah dan sekarang menerima argumen penempatan juga (*args, **kwargs
). Apapun kelompok ditangkap tidak bernama akan sekarang diloloskan ke get_redirect_url()
yang mungkin menghasilkan sebuah TypeError
jika anda tidak memperbaharui tanda tangan dari metode penyesuaian anda.
Pengelolaan transaksi sepenuhnya dirombak di Django 1.6, dan API saat ini diusangkan:
django.middleware.transaction.TransactionMiddleware
django.db.transaction.autocommit
django.db.transaction.commit_on_success
django.db.transaction.commit_manually
TRANSACTIONS_MANAGED
django.contrib.comments
¶Kerangka kerja komentar Django telah diusangkan dan tidak lagi didukung. Itu akan tersedia di Django 1.6 dan 1.7, dan dipindahkan di Django 1.8. Kebanyakan pengguna akan menjadi lebih baik dilayani dengan pemecahan penyesuaian, atau produk disimpan seperti Disqus.
Kode dahulu dikenal sebagai django.contrib.comments
still available in an external repository.
Akhir dari masa dukungan hulu telah tercapai di Desember 2011 untuk PostgreSQL 8.2 dan di February 2013 untuk 8.3. Sebagai konsekuensinya, Django 1.6 menyetel 8.4 sebagai versi minimal PostgreSQL itu secara resmi dukung.
Anda sangat didorong menggunakan versi paling terakhir dari PostgreSQL tersedia, karena dari perbaikan peningkatan dan untuk mengambil keuntungan dari replikasi aliran alamiah tersedia di PostgreSQL 9.x.
cycle
dan firstof
¶Sistem cetakan umumnya meloloskan semua variabel untuk menghindari serangan XSS. Bagaimanaoun, karena sebuah kecelakaan sejarah, etiket cycle
dan firstof
membangun argumen mereka dengan adanya.
Django 1.6 mulai mengolah untuk memperbaiki ketidak konsistenannya. Pustaka cetakan future
menyediakan penerapan lain dari cycle
dan firstof
yang meloloskan otomatis masukan mereka. Jika anda sedang menggunakan etiket ini, anda dianjurkan untuk menyertakan baris berikut pada atas dari cetakan anda untuk mengadakan perilaku baru:
{% load cycle from future %}
atau:
{% load firstof from future %}
Etiket menerapkan perilaku lama telah diusangkan, dan di Django 1.8, perilaku lama akan diganti dengan perilaku baru. Untuk memastikan kesesuaian dengan versi masa depan dari Django, cetakan yang ada harus dirubah untuk menggunakan versi future
.
Jika diperlukan, anda dapat sementara meniadakan pelolosan-otomatis dengan mark_safe()
atau {% autoescape off %}
.
CACHE_MIDDLEWARE_ANONYMOUS_ONLY
¶CacheMiddleware
dan UpdateCacheMiddleware
digunakan untuk menyediakan cara untuk menyimpan sementara permintaan hanya jika mereka tidak dibuat oleh pengguna masuk. Mekanisme ini telah sebagian besar tidak efektif karena middleware dengan benar mengambil kedalam akun kepala HTTP Vary: Cookie
, dan kepala ini sedang dikirim di berbagai kesempatan, seperti:
Ini membuat tembolok secara efektif bekerja pada berdasarkan per-sesi tanpa memperhatikan pengaturan CACHE_MIDDLEWARE_ANONYMOUS_ONLY
.
SEND_BROKEN_LINK_EMAILS
¶CommonMiddleware
digunakan untuk menyediakan pelaporan dasar dari tautan rusak oleh surel ketika SEND_BROKEN_LINK_EMAILS
disetel menjadi True
.
Karena masalah pengurutan yang keras kepala diantara CommonMiddleware
dan LocaleMiddleware
, fitur ini telah dipisah menjadi middleware: BrokenLinkEmailsMiddleware
.
Jika anda bergantung pada fitur ini, anda harus menambah 'django.middleware.common.BrokenLinkEmailsMiddleware'
ke pengaturan MIDDLEWARE_CLASSES
anda dan memindahkan SEND_BROKEN_LINK_EMAILS
dari pengaturan anda.
Jika anda menentukan widget formulir anda sendiri dan menentukan metode _has_changed
pada sebuah widget anda harus sekarang menentukan metode ini di bidang formulir itu sendiri.
module_name
atribut _meta¶Model._meta.module_name
telah dinamai kembali ke model_name
. Meskipun menjadi sebuah API pribadi, itu akan melalui jalur pengusangan biasa.
get_(add|change|delete)_permission
_meta methods¶Metode Model._meta.get_(add|change|delete)_permission
telah diusangkan. Bahkan jika mereka adalah bukan bagian dari API umum mereka akan juga pergi melalui jalur pengusangan biasa. Anda dapat mengganti mereka dengan django.contrib.auth.get_permission_codename('action', Model._meta)
dimana 'action'
adalah 'add'
, 'change'
, atau 'delete'
.
get_query_set
dan metode mirip dinamai kembali menjadi get_queryset
¶Metode yang mengembalikan sebuah QuerySet
seperti Manager.get_query_set
atau ModelAdmin.queryset
telah dinamai menjadi get_queryset
.
Jika anda sedang menulis pustaka yang menerapkan, sebagai contoh, sebuah metode Manager.get_query_set
, dan anda butuh mendukung versi Django lama, anda harus menamai kembali cara dan kondisional tambah sebuah nama lain dengan nama lama:
class CustomManager(models.Manager):
def get_queryset(self):
pass # ...
if django.VERSION < (1, 6):
get_query_set = get_queryset
# For Django >= 1.6, models.Manager provides a get_query_set fallback
# that emits a warning when used.
Jika anda sedang menulis pustaka yang butuh memanggil metode get_queryset
dan harus mendukung versi Django lama, anda harus menulis:
get_queryset = (some_manager.get_query_set
if hasattr(some_manager, 'get_query_set')
else some_manager.get_queryset)
return get_queryset() # etc
Di kasus umum dari penyesuaian pengelola yang kedua menerapkan metode get_queryset
milik nya dan memanggil metode itu, dan butuh bekerja dengan versi Django terlama, dan pustaka yang belum diperbaharui, itu adalah berguna untuk menentukan sebuah metode get_queryset_compat
seperti dibawah dan menggunakannya secara internal ke pengelola anda:
class YourCustomManager(models.Manager):
def get_queryset(self):
return YourCustomQuerySet() # for example
if django.VERSION < (1, 6):
get_query_set = get_queryset
def active(self): # for example
return self.get_queryset_compat().filter(active=True)
def get_queryset_compat(self):
get_queryset = (self.get_query_set
if hasattr(self, 'get_query_set')
else self.get_queryset)
return get_queryset()
Ini membantu mengecilkan perubahan yang dibutuhkan, tetapi juga bekerja dengan benar di kasus dari subkelas (seperti RelatedManagers
dari Django 1.5) yang mungkin menimpa salah satu get_query_set
atau get_queryset
.
jalan pintas
dan URLconf¶Tampilan jalan pintas
dipindahkan dari django.views.defaults
ke django.contrib.contenttypes.views
segera setelah terbitan 1.0, tetapi tempat lama tidak pernah diusangkan. Kekeliruan ini diperbaiki di Django 1.6 dan anda seharusnya sekarang gunakan tempat baru.
URLconf django.conf.urls.shortcut
juga telah diusangkan. Jika anda sedang menyertakan itu di sebuah URLconf, cukup ganti:
(r'^prefix/', include('django.conf.urls.shortcut')),
dengan:
(r'^prefix/(?P<content_type_id>\d+)/(?P<object_id>.*)/$', 'django.contrib.contenttypes.views.shortcut'),
ModelForm
tanpa fields
atau exclude
¶Sebelumnya, jika anda ingin sebuah ModelForm
untuk memakai semua bidang pada model, anda dapat cukup menghilangkan atribut Meta.fields
, dan semua bidang akan digunakan.
Ini dapat membawa pada masalah keamanan dimana bidang ditambahkan ke model dan, tidak sengaja, secara otomatis menjadi dapat disunting oleh pengguna akhir. Di beberapa kasus, khususnya dengan bidang boolean, itu memungkinkan untuk masalah ini secara lengkap nampak. Ini adalah sebuah formulir Mass assignment vulnerability.
Untuk alasan ini, perilaku ini diusangkan, dan menggunakan pilihan Meta.exclude
sangat kecil. Meskipun semua bidang yang dimaksud untuk penyertaan di formulir harus didaftarkan secara eksplisit di atribut field
.
Jika perhatian keamanan sangat tidak berlaku di kasus anda, ada sebuah jalan pintas untuk secara eksplisit mengindikasikan bahwa semua bidang harus digunakan - gunakan nilai khusus ``"__all__"` untuk atribut bidang:
class MyModelForm(ModelForm):
class Meta:
fields = "__all__"
model = MyModel
Jika anda mempunyai penyesuaian ModelForms
yang hanya butuh digunakan di admin, ada pilihan lain. Admin mempunyai metode sendiri untuk menentukan bidang (fieldsets
dll), dan juga menambahkan daftar dari bidang ke ModelForm
adalah berlebihan. Sebagai gantinya, cukup hilangkan kelas sebelah dalam Meta
dari ModelForm
, atau hilangkan atribut Meta.model
. Sejak subkelas ModelAdmin
mengetahui model mana ini untuk, itu dapat menambahkan atribut yang dibutuhkan untuk memperoleh fungsi ModelForm
. Perilaku ini juga bekerja untuk versi Django lebih awal.
UpdateView
dan CreateView
tanpa bidang eksplisit¶Tampilan umum CreateView
dan UpdateView
, dan apapun diperoleh dari ModelFormMixin
, adalah rentan pada masalah keamanan digambarkan di bagian diatas, karena mereka dapat secara otomatis membuat sebuah ModelForm
yang menggunakan semua bidang untuk sebuah model.
Untuk alasan ini, jika anda menggunakan tampilan ini untuk menyunting model, adna harus juga memasok atribut field
(baru di Django 1.6), yaitu sebuah daftar bidang model dan bekerja di cara sama seperti atribut ModelForm
Meta.fields
. Cara lain, anda dapat menyetel atribut form_class
ke ModelForm
yang secara jelas menentukan bidang-bidang akan digunakan. Menentukan sebuah subkelas UpdateView
or CreateView
untuk digunakan dengan sebuah model tetapi tanpa sebuah daftar jelas dari bidang-bidang adalah diusangkan.
ManyToManyField
¶Semua penanganan khusus dari atribut help_text
dari bidang model ManyToManyField
dilakukan oleh model standar atau bidang formulir model seperti digambarkan di Teks bantuan dari bidang formulir model untuk bidang ManyToManyField diatas adalah diusangkan dan akan dipindahkan di Django 1.8.
Teks bantuan dari bidang-bidang ini akan butuh ditangani antara oleh aplikasi, penyesuaian bidang formulir atau widget, cukup seperti terjadi dengan sisa dari jenis bidang model.
Des 02, 2017