मुझे पता है कि मेरा जवाब थोड़ा देर हो गया है, लेकिन इस प्रश्न का दूसरा भाग बिल्कुल है जो मुझे कुछ दिनों पहले चाहिए था।
तो, सबसे पहली बात:
-
वहाँ Django pre_delete संकेत का उपयोग कर रिकॉर्ड की एक हटाना बंद करने के लिए एक रास्ता है?
नहीं वास्तव में, thedk द्वारा प्रस्तावित एक को छोड़कर। और ईमानदारी से, कोई भी नहीं होना चाहिए। क्यूं कर? क्योंकि pre_delete किसी ऑब्जेक्ट को हटाने से पहले होने वाली किसी क्रिया के लिए है। यदि आप हटाने को रोकते हैं, तो यह अब pre_delete नहीं है (दुष्चक्र को नोटिस करें?)
-
वहाँ है कि पहले मूल फ़ाइल को हटाने के लिए एक फ़ाइल को बदलने से पहले एक मॉडल के लिए कहने के लिए एक तरीका है?
हाँ, वहाँ है, और आप इसे काफी अधिकार मिल गया। मैंने एक और सामान्य कोड बनाया है, जो किसी भी मॉडल के लिए काम करेगा जिसमें फ़ाइल ऑब्जेक्ट्स संबंधित हैं (नीचे देखें)। हालांकि, आपको read why को फोरहैंड करना चाहिए यह व्यवहार Django 1.3 में हटा दिया गया था और देखें कि यह किसी भी तरह से आपके तर्क को प्रभावित करता है या नहीं। यह मुख्य रूप से संबंधित मॉडलों से रोलबैक और एक ही फ़ाइल के एकाधिक संदर्भों को कैसे संभालने से संबंधित है।
def delete_files_from_instance(instance, field_names):
for field_name in field_names:
field_value = getattr(instance, field_name, None)
if field_value:
if isinstance(field_value, File):
try:
os.remove(field_value.path)
except OSError:
pass
@receiver(pre_delete)
def on_delete(sender, instance, **kwargs):
# When an object is deleted, all associated files are also removed
delete_files_from_instance(instance, sender._meta.get_all_field_names())
@receiver(pre_save)
def on_update(sender, instance, **kwargs):
# When an object is updated, if any media files are replaced, the old ones should be deleted.
from_fixture = 'raw' in kwargs and kwargs['raw'] # this prevents errors when loading files from fixtures
is_valid_app = sender._meta.app_label in VALID_APPS # Define what apps are targeted by your code
if is_valid_app and not from_fixture:
try:
old_instance = sender.objects.filter(pk=instance.id).first()
if old_instance and old_instance is not None:
delete_files_from_instance(old_instance, sender._meta.get_all_field_names())
except LookupError:
pass
कृपया ध्यान में रखना यह मानता है कि कि आपके हटाने/अद्यतन कार्रवाई सफल हो जाएगा। यदि यह विफल रहता है, तो आपने स्थायी रूप से एक फ़ाइल खो दी है।
एक बेहतर दृष्टिकोण संकेतों post_save/post_delete में फ़ाइल हटाने की संभाल करने के लिए, या एक क्रॉन जॉब जो समय समय पर जो अब डेटाबेस द्वारा दर्शाया जाता है सभी फाइलों को साफ बनाने के लिए किया जाएगा।
मैं यह नहीं करूँगा। हां यह कस्टम दृश्य के लिए काम करता है, लेकिन व्यवस्थापक के माध्यम से ऑब्जेक्ट को हटाने का प्रयास करने वाला कोई व्यक्ति ग़लत त्रुटि प्राप्त करेगा यदि उस अपवाद को उठाया गया हो और संभाला न जाए। – shadfc
आप बिल्कुल सही हैं। जैसा कि मैंने कहा, यह बदसूरत हैक है। – thedk
मुझे नहीं लगता कि यह सभी परिस्थितियों में एक हैक है। जब प्रयास हटाना केवल गलत परिस्थितियों में हो सकता है, तो अपवाद फेंकना सही प्रतिक्रिया की तरह लगता है। – Teekin