Bagaimana saya bisa mendapatkan daftar semua objek model yang memiliki ForeignKey yang menunjuk ke suatu objek? (Sesuatu seperti halaman konfirmasi hapus di admin Django sebelum DELETE CASCADE).
Saya mencoba menemukan cara umum untuk menggabungkan objek duplikat dalam database. Pada dasarnya saya ingin semua objek yang memiliki poin ForeignKeys ke objek "B" diperbarui agar mengarah ke objek "A" sehingga saya dapat menghapus "B" tanpa kehilangan sesuatu yang penting.
Terima kasih atas bantuan Anda!
python
django
django-models
merge
erikcw
sumber
sumber
set
objek terkait mengarah ke A?Jawaban:
Django <= 1.7
Ini memberi Anda nama properti untuk semua objek terkait:
links = [rel.get_accessor_name() for rel in a._meta.get_all_related_objects()]
Anda kemudian dapat menggunakan sesuatu seperti ini untuk mendapatkan semua objek terkait:
for link in links: objects = getattr(a, link).all() for object in objects: # do something with related object instance
Saya menghabiskan waktu untuk mencoba mencari tahu hal ini sehingga saya dapat menerapkan semacam "Pola Pengamat" pada salah satu model saya. Semoga bermanfaat.
Django 1.8+
Gunakan
_meta.get_fields()
: https://docs.djangoproject.com/en/1.10/ref/models/meta/#django.db.models.options.Options.get_fields (lihat juga sebaliknya di_get_fields()
sumber)sumber
all()
akan gagal pada aOneToOneField
. Anda harus mendeteksinya entah bagaimana._meta.get_fields()
: docs.djangoproject.com/en/1.10/ref/models/meta/… (lihat jugareverse
di_get_fields()
sumbernya)_meta.get_fields()
tip, ini adalah bagian dari solusi untuk saya:links = [field.get_accessor_name() for field in obj._meta.get_fields() if issubclass(type(field), ForeignObjectRel)]
(diberikanfrom django.db.models.fields.related import ForeignObjectRel
)@digitalPBK sudah dekat ... di sini mungkin yang anda cari untuk menggunakan barang bawaan Django yang digunakan dalam admin Django untuk menampilkan obyek terkait selama penghapusan
from django.contrib.admin.utils import NestedObjects collector = NestedObjects(using="default") #database name collector.collect([objective]) #list of objects. single one won't do print(collector.data)
ini memperbolehkan anda untuk membuat apa yang ditampilkan oleh admin Django - obyek terkait yang akan dihapus.
sumber
Collector
(diimpor pada baris 1) tidak digunakan?Cobalah ini.
class A(models.Model): def get_foreign_fields(self): return [getattr(self, f.name) for f in self._meta.fields if type(f) == models.fields.related.ForeignKey]
sumber
Berikut ini adalah apa yang django gunakan untuk mendapatkan semua objek terkait
from django.db.models.deletion import Collector collector = Collector(using="default") collector.collect([a]) print collector.data
sumber
links = [rel.get_accessor_name() for rel in a._meta.get_all_related_objects()]
Anda kemudian dapat menggunakan sesuatu seperti ini untuk mendapatkan semua objek terkait:
for link in links: objects = getattr(a, link.name).all() for object in objects: # do something with related object instance
Dari dokumen resmi Django 1.10:
[ f for f in MyModel._meta.get_fields() if (f.one_to_many or f.one_to_one) and f.auto_created and not f.concrete ]
Jadi dengan mengambil contoh yang disetujui kami akan menggunakan:
links = [ f for f in MyModel._meta.get_fields() if (f.one_to_many or f.one_to_one) and f.auto_created and not f.concrete ] for link in links: objects = getattr(a, link.name).all() for object in objects: # do something with related object instance
sumber
python for link in links: objects = getattr(a, link.name).all() for object in objects:
for link in links: objects = getattr(a, link).all()
Berfungsi untuk set terkait, tetapi tidak untuk ForeignKeys. Karena RelatedManagers dibuat secara dinamis, melihat nama kelas lebih mudah daripada melakukan isinstance ()
objOrMgr = getattr(a, link) if objOrMgr.__class__.__name__ == 'RelatedManager': objects = objOrMgr.all() else: objects = [ objOrMgr ] for object in objects: # Do Stuff
sumber
Django 1.9
get_all_related_objects () tidak digunakan lagi
#Example: user = User.objects.get(id=1) print(user._meta.get_fields())
Catatan: RemovedInDjango110Warning: 'get_all_related_objects adalah API tidak resmi yang sudah tidak digunakan lagi. Anda mungkin bisa menggantinya dengan 'get_fields ()'
sumber
Berikut adalah cara lain untuk mendapatkan daftar bidang (hanya nama) dalam model terkait.
def get_related_model_fields(model): fields=[] related_models = model._meta.get_all_related_objects() for r in related_models: fields.extend(r.opts.get_all_field_names()) return fields
sumber
Sayangnya, user._meta.get_fields () hanya mengembalikan relasi yang dapat diakses dari pengguna, namun, Anda mungkin memiliki beberapa objek terkait, yang menggunakan related_name = '+'. Dalam kasus seperti itu, relasi tidak akan dikembalikan oleh user._meta.get_fields (). Oleh karena itu, jika Anda membutuhkan cara umum dan kuat untuk menggabungkan objek, saya sarankan untuk menggunakan Collector yang disebutkan di atas.
sumber