2015-03-20 20 views
8

Eh, şimdi Django 1.6+Django:

kullanıyorum yabancı anahtarların bütün ters referanslar bulmak Ve ben bir modeli vardır:

class FileReference(models.Model): 
    # some data fields 
    # ... 
    pass 

class Person(models.Model): 
    avatar = models.ForeignKey(FileReference, related_name='people_with_avatar') 

class House(models.Model): 
    images = models.ManyToManyField(FileReference, related_name='houses_with_images') 

class Document(model.Model): 
    attachment = models.OneToOneField(FileReference, related_name='document_with_attachment') 

Yani, diğer birçok modeli atıfta yabancı anahtara sahip olacak FileReference modeline.

Ancak bazen, başvurulan modeller FileReference nesnesi sola silinir.

FileReference nesnelerini yabancı anahtar referansı olmadan silmek istiyorum.

Ancak diğer birçok yerde yabancı anahtarlar olacaktır.

Tüm referansları bulmak için etkili bir yol var mı? Yani, bazı model nesnelerin referans sayısını almak?

+2

"Toplayıcı" yı kullanın: http://stackoverflow.com/a/12162619/548165 – catavaran

+0

@catavaran, "collector.collect (file_ref_obj)" adını verdiğimde, şunu denedim: 'TypeError:' FileReference ' nesne indekslemeyi desteklemiyor ' –

+0

Tek örnekle bir liste geçirin: 'collector.collect ([file_ref_obj])' – catavaran

cevap

0

Bu soruya tökezledim ve sizin için bir çözüm buldum. django==1.6 artık desteklenmediğini, unutmayın, bu nedenle bu çözüm muhtemelen şimdilik nesnelerin yaklaşık 2 bahsediyoruz Diyelim django>=1.9

üzerinde çalışacak: Eğer ForeignKey.on_delete belgelerinde görebileceğiniz gibi

class FileReference(models.Model): 
    pass 

class Person(models.Model): 
    avatar = models.ForeignKey(FileReference, related_name='people_with_avatar', on_delete=models.CASCADE) 

, İlgili FileReference nesnesini sildiğinizde, başvurulan nesne Person da silinir.

Sorunuz için şimdi. Saygılar nasıl yapılır? Person deliğinin üzerine FileReference nesnesinin de kaldırılmasını istiyoruz.

Biz post_delete signal kullanarak yapacak: Biz Person silinmesi üzerine avatar alanında referans orada silme bırakmaktı Ne

def delete_reverse(sender, **kwargs): 
    try: 
     if kwargs['instance'].avatar: 
      kwargs['instance'].avatar.delete() 
    except: 
     pass 

post_delete.connect(delete_reverse, sender=Person) 

. Döngü istisnalarını önlemek için try: except: bloğuna dikkat edin.

Ekstra:

yukarıdaki çözüm gelecekteki tüm nesneler üzerinde çalışacak. Paketinizin aşağıdaki dosyayı ve dizinleri eklemek yılında

: Bir referans olmadan geçmiş tüm nesneleri kaldırmak istiyorsanız aşağıdakileri yapın management/commands/remove_unused_file_reference.py bitirdiniz

from django.core.management.base import BaseCommand, CommandError 


class Command(BaseCommand): 

    def handle(self, *args, **options): 

     file_references = FileReference.objects.all() 
     file_reference_mapping = {file_reference.id: file_reference for file_reference in file_references} 

     persons = Person.objects.all() 
     person_avatar_mapping = {person.avatar.id: person for person in persons} 


     for file_reference_id, file_reference in file_reference_mapping.items(): 
      if file_reference_id not in person_avatar_mapping: 
       file_reference.delete() 

, çağrı: python manage.py remove_unused_file_reference budur temel fikir, toplu olarak silebilir vb. silebilirsiniz ...

Umarım bu, birilerine yardım eder. İyi şanslar!