Pengolahan Tampilan Bersyarat¶
Klien HTTP dapat mengirim sejumlah kepala untuk memberitahu peladen tentang salinan dari sumber daya yang mereka sudah lihat. Ini adalah umumnya digunakan ketika mengambil sebuah halaman Jaringan (menggunakan sebuah permintaan GET
HTTP) untuk menghidnari mengirim semua data untuk sesuatu klien sudah ambil. Bagaimanapun, kepala sama dapat digunakan untuk semua metode HTTP (POST
, PUT
, DELETE
, dll.).
Untuk setiap halaman (tanggapan) yang Django kirim kembali dari tampilan, itu mungkin menyediakan dua kepala HTTP: kepala ETag
dan Last-Modified
. Kepala-kepala ini pilihan pada tanggapan HTTP. Mereka dapat disetel dengan fungsi tampilan anda, anda dapat bergantung pada middleware ConditionalGetMiddleware
untuk menyetel kepala ETag
.
Ketika klien selanjutnya meminta sumber daya sama, itu mungkin mengirim sepanjang kepala seperti antara If-modified-since atau If-unmodified-since, mengandung tanggal dari waktu perubahan terakhir itu telah kirim, atau antara If-match atau If-none-match, mengandung ETag
terkahir itu telah kirim. Jika versi saat ini dari halaman cocok ETag
dikirim oleh klien, atau jika sumber daya belum dirubah, sebuah kode keadaan 304 dapat dikirm kembali, sebagai ganti dari tanggapan penuh, memberitahu klien bahwa tidak ada yang berubah. Bergantung pada kepala, jika halaman telah dirubah atau tidak cocok ETAG
dikirim oleh klien, sebuah kode keadaan 412 (Kegagalan Prakondisi) mungkin dikembalikan.
Ketika anda butuh lebih kendali lebih-halus anda mungkin menggunakan fungsi pengolahan bersyarat per-tampilan.
Penggias condition
¶
Terkadang (faktanya, sangat sering) anda dapat membuat fungsi dengan cepat menghitung nilai ETag atau waktu perubahan-terakhir untuk sebuah sumber daya, tanpa membutuhkanmelakukan semua perhitungan dibutuhkan untuk membangun tampilan penuh. Django dapat kemudian menggunakan fungsi-fungsi ini untuk menyediakan sebuah pilihan "early bailout" untuk pengolahan tampilan. Memberitahu klien bahwa isi belum dirubah sejak permintaan terakhir, mungkin.
Dua fungsi ini dilewatkan sebagai parameter pada penghias django.views.decorators.http.condition
. Penghias ini menggunakan dua fungsi (anda hanya butuh menyokong satu, jika anda tidak dapat menghitung kedua jumlah dengan mudah dan cepat) untuk bekerja jika kepala dalam permintaan HTTP cocok dengan itu pada sumber daya. Jika mereka tidak cocok, sebuah salinan baru dari sumber daya harus dihitung dan tampilan biasa anda dipanggil.
Tanda tangan penghias condition
terlihat seperti ini:
condition(etag_func=None, last_modified_func=None)
Dua fungsi, untuk menghitung ETag dan waktu terkahir dirubah, akan dilewatkan obyek request
datang dan parameter sama, dalam urutan sama, ketika fungsi tampilan mereka bantu untuk membungkus. Fungsi dilewatkan last_modified_func
harus mengembalikan sebuah nilai datetime standar menentukan waktu terakhir sumber daya telah dirubah, atau None
jika sumber daya tidak ada. Fungsi dilewatkan ke penghias etag
harus mengembalikan sebuah string mewakili ETag_ untuk sumber daya, atau None
jika itu tidak ada.
Penghias menyetel kepala ETag
dan Last-Modified
pada tanggapan jika mereka tidak disetel oleh tampilan dan jika metode permintaan adalah aman (GET
or HEAD
).
Menggunakan fitur berguna ini mungkin dijelaskan terbaik dengan sebuah contoh. Kiranya anda mempunyai pasangan model ini, mewakili sebuah sistem blog sederhana:
import datetime
from django.db import models
class Blog(models.Model):
...
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
published = models.DateTimeField(default=datetime.datetime.now)
...
Jika halaman depan, menampilkan masukan blog terakhir, hanya perubahan ketika anda menambah masukan blog baru, anda dapat menghitung waktu terakhir dirubah sangat cepat. Anda butuh tanggal published
terakhir untuk setiap masukan terkait dengan blog itu. Satu cara melakukan ini adalah:
def latest_entry(request, blog_id):
return Entry.objects.filter(blog=blog_id).latest("published").published
Anda lalu dapat menggunakan fungsi ini untuk menyediakan pengenalan awal dari halaman tidak berubah untuk tampilan halaman depan anda:
from django.views.decorators.http import condition
@condition(last_modified_func=latest_entry)
def front_page(request, blog_id):
...
Hati-hati dengan urutan dari penghias
Ketika condition()
mengembalikan tanggapan keadaan, penghias apapun dibawah itu akan dilewati dan tidak akan diberlakukan ke tanggapan. Karena itu, penghias apapun yang butuh diberlakukan ke kedua tanggapan tampilan biasa dan tanggapan keadaan harus diatas condition()
. Khususnya, vary_on_cookie()
, vary_on_headers()
, dan cache_control()
harus datang pertama karena RFC 7232 membutuhkan yang kepala mereka set hadir pada 304 tanggapan.
Jalan pintas untuk hanya menghitung satu nilai¶
Sebagai aturan umum, jika anda dapat menyediakan fngsi untuk menghitung kedua ETag dan waktu perubahan terakhir, anda harus melakukannya. Anda tidak mengetahui kepala klien HTTP diberikan akan mengirim anda, jadi bersiap-siap untuk menangani keduanya, terkadang hanya satu nilai adalah mudah untuk dihitung dan Django menyediakan penghias yang menangani hanya ETag atau hanya perhitungan dirubah-terakhir.
Penghias django.views.decorators.http.etag
dan django.views.decorators.http.last_modified
dilewatkan jenis sama dari fungsi seperti penghias condition
. Tanda tangan mereka adalah:
etag(etag_func)
last_modified(last_modified_func)
Kami dapat menulis contoh paling awal, yang hanya menggunakan fungsi dirubah-terakhir, menggunakan satu dari penghias ini:
@last_modified(latest_entry)
def front_page(request, blog_id):
...
...atau:
def front_page(request, blog_id):
...
front_page = last_modified(latest_entry)(front_page)
Gunakan kondisi
ketika menguji kedua kondisi¶
Itu mungkin terlihat lebih baik bagi beberapa orang mencoba dan mengikat penghias etag
dan last_modified
jika anda ingin mencoba kedua prakeadaan. bagaimanapun, ini akan membawa perilaku tidak benar.
# Bad code. Don't do this!
@etag(etag_func)
@last_modified(last_modified_func)
def my_view(request):
# ...
# End of bad code.
Penghias pertama tidak mengetahui apapun tentang kedua dan mungkin menjawab tanggapan itu tidak dirubah meskipun jika penghias kedua akan menentukan sebaliknya. Penghias condition
menggunakan kedua fugnsi callback secara terus menerus untuk bekerja tindakan tepat diambil.
Menggunakan penghias dengan metode HTTP lain¶
Penghias condition
berguna untuk lebih dari hanya permintaan GET
dan HEAD
(permintaan HEAD
adalah sama seperti GET
dalam keadaan ini). Itu dapat juga digunakan untuk menyediakan pemeriksaan untuk perintaan POST
, PUT
dan DELETE
. Dalam keadaan ini, ide bukan mengembalikan sebuah tanggapan "not modified", tetapi memberitahu klien yang sumber daya mereka sedang mencoba telah dirubah dalam sementara itu.
Sebagai contoh, pertimbangkan pertukaran berikut diantara klien dan peladen:
- Permintaan klien
/foo/
. - Tanggapan peladen dengan beberapa isi dengan sebuah ETag dari
"abcd1234"
. - Klien mengirim sebuah permintaan
PUT
HTTP pada/foo/
untuk memperbaharui sumber daya. Itu juga mengirim sebuah kepalaIf-Match: "abcd1234"
untuk menentukan versi itu coba memperbaharui. - Peladen memeriksa untuk melihat jika sumber daya telah berubah, dengan menghitung ETag cara sama itu lakukan untuk permintaan
GET
(menggunakan fungsi sama). Jika sumber data telah berubah, itu akan mengembalikan kode keadaan 412, berarti "Prasyarat gagal". - Klien mengirim sebuah permintaan
GET
pada/foo/
, setelah menerima tanggapan 412, untuk mengambil sebuah versi terperbaharui dari isi sebelum memperbaharui itu.
Hal terpenting contoh ini menunjukkan bahwa fungsi sama dapat digunakan untuk menghitung ETAg dan nilai perubahan terakhir dalam semua keadaan. Faktanya, anda harus menggunakan fungsi sama, sehingga nilai sama dikembalikan setiap waktu.
Kepala-kepala pengesah dengan metode permintaan tidak-aman
Penghias condition
hanya menyetel kepala-kepala pengesah (ETag
dan Last-Modified
) untuk metode-metode HTTP aman, yaitu GET
and HEAD
. Jika anda berharap mengembalikan mereka di kasus lain, setel mereka dalam tampilan anda. Lihat RFC 7231#section-4.3.4 untuk mempelajari tentang perbedaan diantara menyetel sebuah kepala pengesah dalam tanggapan pada permintaan dibuat dengan PUT
lawan POST
.
Perbandingan dengan pengolahan bersyarat middleware¶
Django menyediakan penanganan GET
bersyarat yang sederhana dan mudah melalui django.middleware.http.ConditionalGetMiddleware
. Selagi mudah digunakan dan cocok untuk banyak keadaan, middleware mempunyai batasan untuk penggunaan lanjutan:
- Itu diberlakukan secara global pada semua tampilan dalam proyek anda.
- Itu tidak menyimpan anda dari membangkitkan tanggapan, yang mungkin mahal.
- Itu hanya sesuai untuk permintaan
GET
HTTP.
Anda harus memilih alat paling sesuai untuk masalah tertentu anda disini. Jika anda mempunyai cara menghitung ETags dan waktu perubahan sangat cepat dan jika beberapa tampilan perlu waktu untuk membangkitkan isi, anda harus mempertimbangkan menggunakan penghias decorator
digambarkan dalam dokumen ini. Jika semuanya sudah berjalan cukup cepat, lekatkan menggunakan middleware dan sejumlah lalu lintas jaringan dikirim kembali ke klien akan masih dikurangi jika tampilan belum berubah.