2009-10-08 12 views
15

Bir sorun yaşıyorum çünkü bazı_widget_instance.delete() kullanarak bir Widget siliyorum. Bir WidgetFile silindiğinde, sabit diskimdeki dosyaları silebilmek için bir override delete() yöntemiyle WidgetFile adlı bir modelim de var. Ben yaşıyorum sorun olduğunu ben Widget silmek ve böyle bununla ilgili WidgetFiles varsa:Bir modelde delete() öğesini nasıl geçersiz kılar ve hala ilgili silme işlemleriyle çalışmasını sağlarım var

class WidgetFile(models.Model): 

    widget = models.ForeignKey(Widget) 

Eh, Araç, bu WidgetFiles silinir olduğunu silmek ama ne zaman silme() yöntemi doesn Ekstra sabit disklerimi çalıştırıyorum. Herhangi bir yardım çok takdir edilir.

+0

Bu sorun, bir pencere öğesi silindiğinde, bağımlılarının her birinde delete() yöntemini tetiklemediğinden (bunun için yabancı anahtar başvurusu olan sınıflar) ortaya çıkmıştır. Sadece ilgili nesneleri DB'den siler. Bu onu daha verimli hale getirir, ancak bunun gibi sorunlara yol açar. – orokusaki

cevap

24

ben bunu anladım:

django-following-relationships-backward

örnek görüyoruz. Sadece bu Widget modeline bu koyun:

def delete(self): 
    files = WidgetFile.objects.filter(widget=self) 
    if files: 
     for file in files: 
      file.delete() 
    super(Widget, self).delete() 

Bu

böylece kod silerek benim özel dosyasını tetikler ilgili nesnelerin her biri üzerinde gerekli silme() yöntemini tetiklemiştir. Daha fazla veritabanı pahalı, evet, ama yine de sabit diskteki dosyaları silmeye çalıştığınızda, db'yi birkaç kez daha vurmak büyük bir masraf değil.

O django sitesinde açıklanan gibi görünmelidir
+0

Celery veya cron'un neden silinmiş dosyanın başka bir işlemden okuma/yazma işlemi için zaten açılmış olabileceği ile benzer bir durumla karşılaşmayacağını düşündüğünüzü açık değil. Her iki durumda da, özel durumu ele almak için kod yazmanız gerekir. –

+2

O bit'i kaldırdım ... 4.5 yıl önce bunun iyi bir fikir olabileceğini düşündüm, ama neden tam olarak emin değilim. – orokusaki

1

some_widget_instance ve Widget veya WidgetFile örneğidir? Çünkü bu, Widget örneğiyse,sınıfındaki özel delete() işlevinizi alamaz.

1

Bu, bir Widget'ın bir WidgetFile öğesine tam olarak bağlanması durumunda yalnızca bu özellik dolu görünüyor. pre-deletesignal: Bu durumda sadece bu soruna olası bir şekilde atmak için bir OneToOneField

# Delete the restaurant; the waiter should also be removed 
>>> r = Restaurant.objects.get(pk=1) 
>>> r.delete() 
+0

true, ancak Django, daha az pahalı olan, aynı zamanda daha az geleneksel olan silme yöntemlerinin her birini tetiklemeden tüm garsonlar üzerinde bir veritabanı seviyesi kütle silme yapar. – orokusaki

1

On-to-one examples: dan kullanmalıdır. (Hiçbir şekilde gerçek bir çözüm bulunmadığını ima etmeyiniz.)

2

Silmeden önce clear()'u kullanarak, ilgili nesne kümesindeki tüm nesneleri kaldırır.

group.link_set.clear() 
group.delete() 
50

geçmek unuttum ve Django külçe fark düşünmeniz gereken dokümanlar. Bir Sorgu Kümesi ile toplu olarak nesne silerken bir nesne için silme() yönteminin, adlı dikkat silme Not geçersiz kılma

Overriding predefined model methods

. Özelleştirilmiş silme mantığının gerçekleştirilmesini sağlamak için, pre_delete ve/veya post_delete sinyallerini kullanabilirsiniz.

Bu snippet'iniz hep istediğini yapamaz anlamına gelir. Signals kullanmak, silmeyle ilgili daha iyi bir seçenektir.

aşağıdaki gitti:

import shutil 
from django.db.models.signals import pre_delete 
from django.dispatch import receiver 

@receiver(pre_delete) 
def delete_repo(sender, instance, **kwargs): 
    if sender == Set: 
     shutil.rmtree(instance.repo) 
0

Django 1.9 itibaren, sadece alan için on_delete=models.CASCADE tanımlamak olsaydı, bu silme tüm ilgili nesneleri kaldıracaktır.

+0

Bu doğru değil. Soru, basamaklı silmeyle ilgili değildir. İlgili "silme" yöntemlerinin çağrılmasını sağlamakla ilgilidir. – orokusaki

İlgili konular