Dalam model saya, saya punya:
class Alias(MyBaseModel):
remote_image = models.URLField(max_length=500, null=True, help_text="A URL that is downloaded and cached for the image. Only
used when the alias is made")
image = models.ImageField(upload_to='alias', default='alias-default.png', help_text="An image representing the alias")
def save(self, *args, **kw):
if (not self.image or self.image.name == 'alias-default.png') and self.remote_image :
try :
data = utils.fetch(self.remote_image)
image = StringIO.StringIO(data)
image = Image.open(image)
buf = StringIO.StringIO()
image.save(buf, format='PNG')
self.image.save(hashlib.md5(self.string_id).hexdigest() + ".png", ContentFile(buf.getvalue()))
except IOError :
pass
Yang bekerja sangat bagus untuk pertama kalinya remote_image
perubahan.
Bagaimana saya bisa mengambil gambar baru ketika seseorang telah memodifikasi remote_image
alias? Dan kedua, apakah ada cara yang lebih baik untuk menyimpan gambar jarak jauh?
django
image
caching
django-models
Paul Tarjan
sumber
sumber
save()
LAGI, itu masih akan berfungsi dengan benar.Saya menggunakan mixin berikut:
Pemakaian:
Catatan
Harap dicatat bahwa solusi ini berfungsi baik dalam konteks permintaan saat ini saja. Jadi itu cocok terutama untuk kasus-kasus sederhana. Dalam lingkungan bersamaan di mana banyak permintaan dapat memanipulasi contoh model yang sama pada saat yang sama, Anda pasti membutuhkan pendekatan yang berbeda.
sumber
Cara terbaik adalah dengan
pre_save
sinyal. Mungkin bukan pilihan di tahun '09 ketika pertanyaan ini diajukan dan dijawab, tetapi siapa pun yang melihat ini hari ini harus melakukannya dengan cara ini:sumber
Dan sekarang untuk jawaban langsung: salah satu cara untuk memeriksa apakah nilai untuk bidang telah berubah adalah dengan mengambil data asli dari database sebelum menyimpan contoh. Pertimbangkan contoh ini:
Hal yang sama berlaku ketika bekerja dengan formulir. Anda dapat mendeteksinya di metode clean atau save dari ModelForm:
sumber
pk is not None
tidak berlaku misalnya jika menggunakan UUIDField. Ini hanya saran yang buruk.@transaction.atomic
Sejak Django 1.8 dirilis, Anda dapat menggunakan from_db classmethod untuk cache nilai lama dari remote_image. Kemudian dalam metode simpan, Anda dapat membandingkan nilai bidang lama dan baru untuk memeriksa apakah nilainya berubah.
sumber
new._loaded_remote_image = new.remote_image
?from_db
dipanggil olehrefresh_from_db
, atribut pada instance (yaitu dimuat atau sebelumnya) tidak diperbarui. Akibatnya, saya tidak dapat menemukan alasan mengapa ini lebih baik daripada__init__
yang Anda masih perlu untuk menangani 3 kasus:__init__
/from_db
,refresh_from_db
, dansave
.Perhatikan bahwa pelacakan perubahan bidang tersedia di django-model-utils.
https://django-model-utils.readthedocs.org/en/latest/index.html
sumber
Jika Anda menggunakan formulir, Anda dapat menggunakan Formulir yang diubah_data ( dokumen ):
sumber
Saya agak terlambat ke pesta tetapi saya menemukan solusi ini juga: Django Dirty Fields
sumber
Pada Django 1.8, ada
from_db
metode, seperti Serge menyebutkan. Bahkan, dokumen Django menyertakan kasus penggunaan khusus ini sebagai contoh:https://docs.djangoproject.com/en/dev/ref/models/instances/#customizing-model-loading
sumber
Ini bekerja untuk saya di Django 1.8
sumber
Anda dapat menggunakan django-model-changes untuk melakukan ini tanpa pencarian basis data tambahan:
sumber
Jawaban terlambat lainnya, tetapi jika Anda hanya mencoba melihat apakah file baru telah diunggah ke bidang file, coba ini: (diadaptasi dari komentar Christopher Adams pada tautan http://zmsmith.com/2010/05/django -check-if-a-field-telah-berubah / dalam komentar zach di sini)
Tautan yang diperbarui: https://web.archive.org/web/20130101010327/http://zmsmith.com:80/2010/05/django-check-if-a-field-has-changed/
sumber
pre_save
penerima juga. Terima kasih telah berbagi ini!Solusi optimal mungkin salah satu yang tidak termasuk operasi pembacaan basis data tambahan sebelum menyimpan instance model, atau pustaka Django lebih lanjut. Inilah mengapa solusi laffuste lebih disukai. Dalam konteks situs admin, seseorang dapat dengan mudah menimpa
save_model
-metode, dan memanggil metode formulir dihas_changed
sana, seperti dalam jawaban Sion di atas. Anda tiba di sesuatu seperti ini, menggambar pada pengaturan contoh Sion tetapi menggunakanchanged_data
untuk mendapatkan setiap kemungkinan perubahan:save_model
:https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_model
changed_data
-metode untuk Field:https://docs.djangoproject.com/en/1.10/ref/forms/api/#django.forms.Form.changed_data
sumber
Meskipun ini tidak benar-benar menjawab pertanyaan Anda, saya akan melakukannya dengan cara yang berbeda.
Cukup kosongkan
remote_image
bidang setelah berhasil menyimpan salinan lokal. Kemudian dalam metode simpan Anda, Anda selalu dapat memperbarui gambar kapan punremote_image
tidak kosong.Jika Anda ingin menyimpan referensi ke url, Anda bisa menggunakan bidang boolean yang tidak dapat diedit untuk menangani flag caching daripada
remote_image
bidang itu sendiri.sumber
Saya mengalami situasi ini sebelum solusi saya adalah untuk menimpa
pre_save()
metode kelas bidang target itu akan dipanggil hanya jika bidang telah diubahberguna dengan contoh FileField:
kerugian:
tidak berguna jika Anda ingin melakukan operasi (post_save) seperti menggunakan objek yang dibuat dalam beberapa pekerjaan (jika bidang tertentu telah berubah)
sumber
meningkatkan jawaban @josh untuk semua bidang:
hanya untuk memperjelas, getattr berfungsi untuk mendapatkan bidang seperti
person.name
dengan string (yaitugetattr(person, "name")
sumber
Saya telah memperpanjang mixin dari @livskiy sebagai berikut:
dan DictField adalah:
itu dapat digunakan dengan memperluasnya dalam model Anda bidang _dict akan ditambahkan ketika Anda menyinkronkan / bermigrasi dan bidang itu akan menyimpan keadaan objek Anda
sumber
Bagaimana dengan menggunakan solusi David Cramer:
http://cramer.io/2010/12/06/tracking-changes-to-fields-in-django/
Saya sudah sukses menggunakannya seperti ini:
sumber
Sebuah modifikasi pada jawaban @ ivanperelivskiy:
Ini menggunakan metode publik Django 1.10
get_fields
sebagai gantinya. Ini membuat kode lebih banyak bukti di masa depan, tetapi yang lebih penting juga mencakup kunci dan bidang asing di mana dapat diedit = Salah.Untuk referensi, berikut adalah implementasinya
.fields
sumber
Inilah cara lain untuk melakukannya.
Sesuai dokumentasi: memvalidasi objek
"Langkah kedua yang dilakukan full_clean () adalah memanggil Model.clean (). Metode ini harus diganti untuk melakukan validasi khusus pada model Anda. Metode ini harus digunakan untuk memberikan validasi model khusus, dan untuk memodifikasi atribut pada model Anda jika diinginkan Misalnya, Anda dapat menggunakannya untuk secara otomatis memberikan nilai untuk suatu bidang, atau untuk melakukan validasi yang memerlukan akses ke lebih dari satu bidang: "
sumber
Ada atribut __dict__ yang memiliki semua bidang sebagai kunci dan nilai sebagai nilai bidang. Jadi kita bisa membandingkan keduanya
Cukup ubah fungsi simpan model ke fungsi di bawah ini
Contoh penggunaan:
menghasilkan output dengan hanya bidang-bidang yang telah diubah
sumber
Sangat terlambat ke permainan, tetapi ini adalah versi jawaban Chris Pratt yang melindungi terhadap kondisi balapan sambil mengorbankan kinerja, dengan menggunakan
transaction
blok danselect_for_update()
sumber
sebagai perpanjangan dari jawaban SmileyChris, Anda dapat menambahkan bidang datetime ke model untuk last_updated, dan menetapkan semacam batas untuk usia maksimum yang akan Anda biarkan sebelum memeriksa perubahan
sumber
Mixin dari @ivanlivski bagus.
Saya telah memperpanjangnya
Kode yang diperbarui tersedia di sini: https://github.com/sknutsonsf/python-contrib/blob/master/src/django/utils/ModelDiffMixin.py
Untuk membantu orang yang baru mengenal Python atau Django, saya akan memberikan contoh yang lebih lengkap. Penggunaan khusus ini adalah untuk mengambil file dari penyedia data dan memastikan catatan dalam database mencerminkan file.
Objek model saya:
Kelas yang memuat file memiliki metode ini:
sumber
Jika Anda tidak menemukan minat dalam
save
metode penggantian , Anda dapat melakukannyasumber