Penghapusan Lunak di Django

Apa itu Penghapusan Lunak?

Terkadang, Anda ingin menghapus sesuatu dari database Anda tanpa benar -benar menghapusnya. Anda ingin menyimpannya, jika Anda memutuskan untuk memulihkannya di masa mendatang, atau menggunakannya untuk tujuan lain, seperti analitik … tetapi itu akan tetap muncul seolah-olah itu benar-benar dihapus, tidak muncul di tempat yang tidak terduga di aplikasi Anda. Ini disebut pola 'hapus lunak'.

Alih-alih benar-benar menghapus catatan dari database Anda, yang tidak dapat diubah, Anda cukup 'menandai' sebagai dihapus, biasanya di kolom lain di tabel Anda. Sekarang tantangannya tetap, bagaimana mencegah catatan yang dihapus dari 'bocor' ke dalam aplikasi Anda.

Dalam artikel ini, kita akan belajar bagaimana mengimplementasikan penghapusan lunak di Django dengan mengambil contoh backend aplikasi pencatat sederhana.

Model Hapus Lembut

Kita akan mulai dengan membuat SoftDeleteModel dasar yang dapat diwarisi oleh model kita yang lain.

 class SoftDeleteModel ( models . Model ): is_deleted = models . BooleanField ( default = False ) def soft_delete ( self ): self . is_deleted = True self . save () def restore ( self ): self . is_deleted = False self . save () class Meta : abstract = True

Perhatikan bahwa kami telah menandai model ini sebagai abstract = True . Ini berarti bahwa Django tidak akan membuat tabel database untuknya.

Sekarang, kita dapat membuat model kita sebagai subclass dari SoftDeleteModel untuk memberi mereka kemampuan untuk dihapus secara lunak. Mari kita ambil contoh model Note

 class Note ( SoftDeleteModel ): user = models . ForeignKey ( User , on_delete = models . CASCADE , related_name = "notes" ) title = models . CharField ( max_length = 32 ) content = models . CharField ( max_length = 255 )

Kami dapat meminta pemfilteran basis data kami dengan is_deleted untuk mengecualikan catatan yang telah dihapus sementara.

 Note . objects . filter ( is_deleted = False )

Mencobanya

Mari kita coba bermain-main sedikit dengan kode yang telah kita tulis sejauh ini. Pertama, buka shell Django dengan mengetik python manage.py shell di terminal Anda.

Impor model yang diperlukan:

 from django.contrib.auth.models import User from tutorialapp.models import Note

Karena setiap catatan diberi kunci asing untuk pengguna, langkah pertama kita adalah membuat objek User :

 john = User . objects . create_user ( 'john' , 'lennon@thebeatles.com' , 'johnpassword' )

Sekarang kita dapat membuat beberapa catatan:

 my_note = Note . objects . create ( user = john , title = "Strawberry Fields" , content = "Strawberry Fields Forever" ) another_note = Note . objects . create ( user = john , title = "Here Comes The Sun" , content = "It's All Right" )

Anda sekarang siap untuk menghapus dan mengembalikan catatan:

 my_note . soft_delete () my_note . restore ()

Anda dapat menanyakan semua catatan, apakah telah dihapus atau belum:

 Note . objects . all ()

Anda juga dapat memfilter hanya untuk catatan yang belum dihapus sementara:

 Note . objects . filter ( is_deleted = False )

Manajer Penghapusan Lunak

Meskipun kode kita secara fungsional benar, kelemahannya adalah kita harus ingat untuk memfilter berdasarkan is_deleted=False setiap kali kita menulis kueri.

Kami dapat memperbaiki perilaku ini dengan membuat manajer model kustom untuk menerapkan filter secara otomatis, di belakang layar. Jika Anda pernah menggunakan Django di masa lalu, Anda mungkin familiar dengan pernyataan yang terlihat seperti ini: MyModel.objects.all() . Bagian .objects dalam pernyataan adalah manajer. Manajer bertindak sebagai 'jembatan' antara kode Django Anda dan database. Mereka mengontrol operasi database yang dilakukan pada tabel yang mereka 'kelola'.

Manajer kustom baru kami dapat didefinisikan sebagai:

 class SoftDeleteManager ( models . Manager ): def get_queryset ( self ): return super (). get_queryset (). filter ( is_deleted = False )

Kita perlu menambahkan manajer baru ke kelas dasar SoftDeleteModel

 class SoftDeleteModel ( models . Model ): is_deleted = models . BooleanField ( default = False ) objects = models . Manager () undeleted_objects = SoftDeleteManager () def soft_delete ( self ): self . is_deleted = True self . save () def restore ( self ): self . is_deleted = False self . save () class Meta : abstract = True

Perhatikan bahwa, karena kita telah menambahkan manajer kustom ke kelas kita, kita juga harus menambahkan manajer objects

Kemudian, kita cukup menulis ulang kueri kita sebagai,

 Note . undeleted_objects . all ()

untuk mendapatkan QuerySet dari catatan yang tidak terhapus.

Kita masih bisa menggunakan

 Note . objects . all ()

untuk mendapatkan daftar lengkap catatan, termasuk yang telah dihapus sementara.

Menangani Hubungan Kunci Asing

Sekarang, bagaimana jika Anda memiliki banyak pengguna, dan Anda ingin mengambil semua catatan milik pengguna tertentu? Pendekatan naif adalah dengan hanya menulis pemfilteran kueri terhadap pengguna:

 Note . objects . filter ( user = john , is_deleted = False )

Namun, solusi yang lebih elegan dan dapat dibaca adalah dengan menggunakan hubungan terbalik yang disediakan Django untuk tujuan ini.

 john . notes . all ()

Coba hapus perlahan beberapa catatan Anda dan jalankan kueri ini. Apakah Anda melihat sesuatu yang tidak biasa tentang hasilnya?

Kami menemukan bahwa QuerySet dihasilkan berisi catatan yang telah kami hapus dengan lembut. Ini karena Django menggunakan objects default untuk melakukan pencarian terbalik, yang, seperti yang Anda ingat, tidak memfilter catatan yang dihapus lunak.

Bagaimana kita bisa memaksa Django untuk menggunakan SoftDeleteManager kustom kita untuk melakukan pencarian terbalik? Kami cukup mengganti manajer objects SoftDeleteModel kami:

 class SoftDeleteModel ( models . Model ): is_deleted = models . BooleanField ( default = False ) objects = SoftDeleteManager () all_objects = models . Manager () def soft_delete ( self ): self . is_deleted = True self . save () def restore ( self ): self . is_deleted = False self . save () class Meta : abstract = True

Sekarang, objects akan secara otomatis memfilter objek yang dihapus sementara saat menanyakan database kami, memastikan objek tersebut tidak pernah bocor ke aplikasi kami dalam keadaan apa pun! Jika kita mau, kita masih bisa memasukkan objek yang dihapus dalam kueri kita dengan menggunakan manajer all_objects

 Note . all_objects . all ()

Menyimpan Lebih Banyak Informasi

Kami telah mendapatkan kerangka penghapusan lunak yang cukup solid di aplikasi Django kami, tetapi kami dapat membuat satu peningkatan terakhir. Mengetahui apakah suatu arsip telah dihapus secara lunak atau tidak adalah berguna, tetapi informasi lain yang sebaiknya diketahui adalah kapan arsip tersebut dihapus secara lunak. Untuk ini, kita dapat menambahkan atribut baru deleted_at ke SoftDeleteModel kita :

 deleted_at = models . DateTimeField ( null = True , default = None )

Kami juga dapat memperbarui soft_delete dan restore sebagai berikut:

 def soft_delete ( self ): self . deleted_at = timezone . now () self . save () def restore ( self ): self . deleted_at = None self . save ()

Untuk arsip yang tidak terhapus, nilai dari deleted_at akan menjadi null, sedangkan untuk arsip yang dihapus sementara, akan berisi tanggal dan waktu penghapusannya.

Penambahan baru deleted_at atribut membuat dibuat sebelumnya kami is_deleted atribut berlebihan, karena kita hanya dapat melakukan null-cek pada deleted_at untuk mengetahui apakah catatan ini lembut dihapus atau tidak.

SoftDeleteModel kami yang ditulis ulang sekarang terlihat seperti ini:

 class SoftDeleteModel ( models . Model ): deleted_at = models . DateTimeField ( null = True , default = None ) objects = SoftDeleteManager () all_objects = models . Manager () def soft_delete ( self ): self . deleted_at = timezone . now () self . save () def restore ( self ): self . deleted_at = None self . save () class Meta : abstract = True

SoftDeleteManager kami yang ditulis ulang terlihat seperti ini:

 class SoftDeleteManager ( models . Manager ): def get_queryset ( self ): return super (). get_queryset (). filter ( deleted_at__isnull = True )

Selain kemampuan kami sebelumnya, sekarang kami juga dapat melihat tanggal dan waktu yang tepat saat catatan kami dihapus secara sementara:

 my_note . deleted_at

Kesimpulannya

Penghapusan lunak adalah pola perangkat lunak yang kuat yang hadir dengan beberapa keunggulan, termasuk pelestarian dan pemulihan data yang lebih baik, pelacakan riwayat, dan pemulihan yang lebih cepat dari kegagalan.

Pada saat yang sama, itu harus digunakan dengan hati-hati. Data sensitif dan pribadi termasuk informasi terkait pembayaran harus selalu dihapus. Pengguna harus selalu memiliki opsi untuk menghapus data mereka secara permanen, jika mereka mau. Beberapa yurisdiksi di seluruh dunia memiliki undang-undang privasi informasi dan perlindungan data yang mencakup 'hak untuk dilupakan', seperti GDPR Uni Eropa . Mungkin juga masuk akal untuk menghapus atau mengarsipkan data yang sangat lama secara berkala, untuk menghindari memakan ruang penyimpanan basis data yang berlebihan.

Jika Anda ingin melihat kode sumber lengkap untuk contoh yang digunakan dalam tutorial ini, tersedia di GitHub .

Image by Makalu dari Pixabay

Referensi dan Bacaan Lebih Lanjut

Cara menggunakan manajer di Django
Apa Itu Penghapusan Lunak, dan Bagaimana Penerapannya?
Penghapusan Lunak di Django

July 3, 2021

codeorayo

Ampuh! Ini rahasia mengembangkan aplikasi secara instan, tinggal download dan kembangkan. Gabung sekarang juga! Premium Membership [PRIVATE] https://premium.codeorayo.com

Leave a Reply

Your email address will not be published. Required fields are marked *