আমি যখন ডেটাবেস / মডেল থেকে কোনও বস্তু সরিয়ে ফেলি তখন ফাইলগুলি মুছে ফেলার জন্য আমি জাঙ্গো অ্যাডমিন কীভাবে পাব?


86

আমি একটি স্ট্যান্ডার্ড ইমেজফিল্ড সহ 1.2.5 ব্যবহার করছি এবং অন্তর্নির্মিত স্টোরেজ ব্যাকএন্ড ব্যবহার করছি। ফাইলগুলি ঠিকঠাক আপলোড করে তবে আমি প্রশাসক থেকে কোনও এন্ট্রি সরিয়ে ফেললে সার্ভারের আসল ফাইলটি মুছবে না।


এইচএম, আসলে এটি করা উচিত। আপনার আপলোড ফোল্ডারে ফাইল অনুমতি পরীক্ষা করুন (0777 এ পরিবর্তন করুন)।
টর্স্টেন এঞ্জেলব্রেচ্ট

4
জ্যাঙ্গো স্বয়ংক্রিয়ভাবে মুছে ফেলা বৈশিষ্ট্যটি সরিয়ে দিয়েছে (গুগলারের জন্য যারা উপরের মন্তব্যটি দেখেছেন)।
চিহ্নিত করুন

উত্তর:


102

আপনি pre_deleteবা post_deleteসিগন্যালটি পেতে পারেন (নীচে @ টোটো_টিকোর মন্তব্য দেখুন) এবং ফাইলফিল্ড অবজেক্টে মুছুন () পদ্ধতিটি কল করতে পারেন , এইভাবে (মডেল.পাইতে):

class MyModel(models.Model):
    file = models.FileField()
    ...

# Receive the pre_delete signal and delete the file associated with the model instance.
from django.db.models.signals import pre_delete
from django.dispatch.dispatcher import receiver

@receiver(pre_delete, sender=MyModel)
def mymodel_delete(sender, instance, **kwargs):
    # Pass false so FileField doesn't save the model.
    instance.file.delete(False)

11
instance.fileক্ষেত্রটি ফাঁকা না থাকলে বা পুরো MEDIA_ROOT ডিরেক্টরি মুছতে (অন্তত চেষ্টা করতে পারেন) তা নিশ্চিত করার জন্য নিশ্চিত হন । এটি এমনকি ImageField(null=False)ক্ষেত্রগুলিতে প্রযোজ্য ।
অ্যান্টনি হ্যাচকিন্স

49
ধন্যবাদ সাধারণভাবে, আমি post_deleteসিগন্যালটি ব্যবহার করার পরামর্শ দেব কারণ এটি নিরাপদ কারণেই কোনও কারণে মুছা ব্যর্থ হয়। তারপরে মডেল, না কোনও ফাইলই ডেটা ধারাবাহিক রেখে মুছে ফেলা হবে না। আমার বোঝার post_deleteএবং pre_deleteসংকেতগুলি ভুল হলে দয়া করে আমাকে সংশোধন করুন ।
টোটো_টিকো

9
নোট করুন যে আপনি যদি কোনও মডেল উদাহরণে ফাইলটি প্রতিস্থাপন করেন তবে এটি পুরানো ফাইলটি মুছে
চিহ্নিত করুন

4
এটি অ্যাডমিনের বাইরের জাজানো ১.৮ এ আমার পক্ষে কাজ করে না। এটি করার কোনও নতুন উপায় আছে?
খলিফা

অসাধারণ. দীর্ঘকাল এটি খুঁজছিল
আরএল শ্যাম

46

জ্যাঙ্গো-ক্লিনআপ চেষ্টা করুন

pip install django-cleanup

সেটিংস.পি

INSTALLED_APPS = (
    ...
    'django_cleanup', # should go after your apps
)

4
খুব দুর্দান্ত প্যাকেজ। ধন্যবাদ! :)
BoJack Horseman

4
সীমিত পরীক্ষার পরে, আমি নিশ্চিত করতে পারি যে এই প্যাকেজটি এখনও জ্যাঙ্গো 1.10 এর জন্য কাজ করে।
কোডারগুই 123

4
সুন্দর, এটি এত সহজ
টান করুন

ভাল লাগল জ্যাঙ্গো ২.০ এ আমার জন্য কাজ করে। আমি আমার স্টোরেজ ব্যাকএন্ড ( django-storages.readthedocs.io/en/latest/backends/… ) হিসাবে এস 3 ব্যবহার করছি এবং এটি আনন্দের সাথে S3 থেকে ফাইলগুলি মুছে ফেলছে।
রুটবার্ন

35

জ্যাঙ্গো 1.5 সমাধান: আমি আমার অ্যাপ্লিকেশনের অভ্যন্তরীণ বিভিন্ন কারণে পোস্ট_ডিলিট ব্যবহার করি।

from django.db.models.signals import post_delete
from django.dispatch import receiver

@receiver(post_delete, sender=Photo)
def photo_post_delete_handler(sender, **kwargs):
    photo = kwargs['instance']
    storage, path = photo.original_image.storage, photo.original_image.path
    storage.delete(path)

আমি এটি মডেল.পি ফাইলের নীচে আটকে রেখেছি।

original_imageক্ষেত্র ImageFieldআমার মধ্যে Photoমডেল।


7
আমাজন এস 3 কে স্টোরেজ ব্যাকএন্ড হিসাবে ব্যবহার করেন (জ্যাঙ্গো-স্টোরের মাধ্যমে), এই বিশেষ উত্তরটি কাজ করবে না। আপনি একটি পাবেন যা NotImplementedError: This backend doesn't support absolute paths.আপনি storage.delete()ফাইল ক্ষেত্রের পথের পরিবর্তে ফাইল ক্ষেত্রের নামটি পাস করে সহজেই এটি ঠিক করতে পারেন । উদাহরণস্বরূপ, এই উত্তরটির শেষ দুটি লাইনটি storage, name = photo.original_image.storage, photo.original_image.nameতখনই প্রতিস্থাপন করুন storage.delete(name)
শান আজলিন

4
@ সিয়ান +1, আমি জাজো-স্টোরেজগুলির মাধ্যমে এস 3-তে জাজানো-ইমেজকিট দ্বারা উত্পন্ন থাম্বনেইসগুলি মুছতে 1.7 এ সামঞ্জস্যটি ব্যবহার করছি। docs.djangoproject.com/en/dev/ref/files/stores/… । দ্রষ্টব্য: আপনি যদি কেবল চিত্র চিত্র (বা ফাইলফিল্ড) ব্যবহার করেন তবে আপনি mymodel.myimagefield.delete(save=False)পরিবর্তে ব্যবহার করতে পারেন । docs.djangoproject.com/en/dev/ref/files/file/…
ব্যবহারকারী2616836

@ user2616836 আপনি ব্যবহার করতে পারেন mymodel.myimagefield.delete(save=False)উপর post_delete? অন্য কথায়, আমি দেখতে পাচ্ছি যে আমি ফাইলটি মুছে ফেলতে পারি, তবে যখন চিত্রমাটি রয়েছে এমন কোনও মডেল মুছে ফেলা যায় তবে আপনি কি ফাইলটি মুছতে পারবেন?
ইউজিন

4
@ ইউজিন হ্যাঁ আপনি এটি করতে পারেন, এটি কাজ করে (যদিও আমি নিশ্চিত না)। ইন post_deleteআপনি কি instance.myimagefield.delete(save=False), এর ব্যবহার লক্ষ করুন instance
ব্যবহারকারী2616836

17

অ্যাডমিন প্যানেল সহ এই কোডটি জ্যাঙ্গো ১.৪ এ ভাল চলে।

class ImageModel(models.Model):
    image = ImageField(...)

    def delete(self, *args, **kwargs):
        # You have to prepare what you need before delete the model
        storage, path = self.image.storage, self.image.path
        # Delete the model before the file
        super(ImageModel, self).delete(*args, **kwargs)
        # Delete the file after the model
        storage.delete(path)

মডেল বা উত্তরোত্তরটিকে মুছে ফেলার আগে স্টোরেজ এবং পথটি পাওয়া গুরুত্বপূর্ণ, এমনকি যদি মোছা হয় তবে তা অকার্যকর থাকবে।


4
এটি আমার (জ্যাঙ্গো 1.5।) কাজ করে না এবং জ্যাঙ্গো 1.3 চেঞ্জেলওগ জানিয়েছে: "জ্যাঙ্গো ১.৩-এ, যখন কোনও মডেল ফাইলফিল্ডের মুছলে মুছে ফেলা হয় () পদ্ধতিটি কল করা হবে না If যদি আপনাকে অনাথ ফাইলগুলি পরিষ্কার করার প্রয়োজন হয়, আপনি ' এটি নিজেই পরিচালনা করতে হবে (উদাহরণস্বরূপ, একটি কাস্টম ম্যানেজমেন্ট কমান্ড যা ম্যানুয়ালি চালানো যেতে পারে বা যেমন ক্রোনের মাধ্যমে পর্যায়ক্রমে চালানোর জন্য নির্ধারিত হবে) "।
দারিন্ম

4
এই সমাধানটি ভুল! deleteএকটি সারি মুছে ফেলা হলে সর্বদা বলা হয় না, আপনাকে অবশ্যই সংকেত ব্যবহার করতে হবে।
lvella

14

আপনি প্রয়োজন উভয় উপর প্রকৃত ফাইল মুছে ফেলার জন্য deleteএবং update

from django.db import models

class MyImageModel(models.Model):
    image = models.ImageField(upload_to='images')

    def remove_on_image_update(self):
        try:
            # is the object in the database yet?
            obj = MyImageModel.objects.get(id=self.id)
        except MyImageModel.DoesNotExist:
            # object is not in db, nothing to worry about
            return
        # is the save due to an update of the actual image file?
        if obj.image and self.image and obj.image != self.image:
            # delete the old image file from the storage in favor of the new file
            obj.image.delete()

    def delete(self, *args, **kwargs):
        # object is being removed from db, remove the file from storage first
        self.image.delete()
        return super(MyImageModel, self).delete(*args, **kwargs)

    def save(self, *args, **kwargs):
        # object is possibly being updated, if so, clean up.
        self.remove_on_image_update()
        return super(MyImageModel, self).save(*args, **kwargs)

দুর্দান্ত সমাধান!
আলেক্সখ

6

আপনি একটি প্রি-ডিলিট বা পোস্ট_ডিলিট সিগন্যালটি ব্যবহার করে বিবেচনা করতে পারেন:

https://docs.djangoproject.com/en/dev/topics/signals/

অবশ্যই, ফাইলফিল্ড স্বয়ংক্রিয়ভাবে মুছে ফেলা সরানো একই কারণগুলি এখানেও প্রয়োগ হয় apply আপনি যদি এমন কোনও ফাইল মুছেন যা অন্য কোথাও উল্লেখ করা থাকে তবে আপনার সমস্যা হবে।

আমার ক্ষেত্রে এটি উপযুক্ত বলে মনে হয়েছিল কারণ আমার সমস্ত ফাইল পরিচালনা করার জন্য আমার কাছে একটি উত্সর্গীকৃত ফাইল মডেল ছিল।

দ্রষ্টব্য: কিছু কারণে পোস্ট_ডিলিট সঠিকভাবে কাজ করছে বলে মনে হচ্ছে না। ফাইলটি মুছে ফেলা হয়েছে, তবে ডাটাবেস রেকর্ড থেকে যায়, যা ত্রুটি শর্তের মধ্যেও আমি প্রত্যাশা করব সম্পূর্ণ বিপরীত। প্রাক_ডিলিট যদিও ভাল কাজ করে।


4
সম্ভবত post_delete কাজ করবে না, কারণ file_field.delete()ডিফল্টরূপে মডেলকে ডিবি-তে সংরক্ষণ করে, file_field.delete(False) ডকস.ড্যাঞ্জোপ্রজেক্ট
অ্যাডাম জুরজাইক

3

হয়তো কিছুটা দেরি হয়ে গেছে। তবে আমার পক্ষে সবচেয়ে সহজ উপায় হল পোস্ট_সেভ সংকেত ব্যবহার করা। শুধু মনে রাখবেন যে কোয়েরিसेट মুছতে প্রক্রিয়া চলাকালীন সংকেতগুলি অতিক্রম করা হয়, তবে [মডেল] .ডিলিট () পদ্ধতিটি ক্যোরিসেট মোছার প্রক্রিয়া চলাকালীন উত্তম নয়, সুতরাং এটি ওভাররাইড করার সেরা বিকল্প নয়।

কোর / মডেল.পি:

from django.db import models
from django.db.models.signals import post_delete
from core.signals import delete_image_slide
SLIDE1_IMGS = 'slide1_imgs/'

class Slide1(models.Model):
    title = models.CharField(max_length = 200)
    description = models.CharField(max_length = 200)
    image = models.ImageField(upload_to = SLIDE1_IMGS, null = True, blank = True)
    video_embed = models.TextField(null = True, blank = True)
    enabled = models.BooleanField(default = True)

"""---------------------------- SLIDE 1 -------------------------------------"""
post_delete.connect(delete_image_slide, Slide1)
"""--------------------------------------------------------------------------"""

কোর / সিগন্যালস.পি

import os

def delete_image_slide(sender, **kwargs):
    slide = kwargs.get('instance')
    try:
        os.remove(slide.image.path)
    except:
        pass

1

এই কার্যকারিতাটি জ্যাঙ্গো ১.৩ এ সরানো হবে তাই আমি এর উপর নির্ভর করব না।

আপনি ওভাররাইড করতে পারে deleteসম্পূর্ণভাবে ডাটাবেস থেকে এন্ট্রি সরানোর আগে ফাইলটি মুছতে আপনি প্রশ্নে থাকা মডেলটির পদ্ধতিটি ।

সম্পাদনা করুন:

এখানে একটি দ্রুত উদাহরণ।

class MyModel(models.Model):

    self.somefile = models.FileField(...)

    def delete(self, *args, **kwargs):
        somefile.delete()

        super(MyModel, self).delete(*args, **kwargs)

ফাইলটি মোছার জন্য কীভাবে কোনও মডেলটিতে এটি ব্যবহার করবেন তার একটি উদাহরণ আছে? আমি দস্তাবেজগুলিতে দেখছি এবং কীভাবে ডাটাবেস থেকে অবজেক্টটি সরিয়ে ফেলতে হবে তার উদাহরণ দেখুন তবে ফাইল মোছার কোনও বাস্তবায়ন দেখতে পাচ্ছেন না।
নারকীসো

4
এই পদ্ধতিটি ভুল কারণ এটি বাল্ক মুছার জন্য কাজ করে না (যেমন প্রশাসকের 'মুছুন নির্বাচন করুন' বৈশিষ্ট্যটি)। উদাহরণস্বরূপ MyModel.objects.all()[0].delete(), ফাইলটি মুছে MyModel.objects.all().delete()ফেলবে যখন না করবে। সিগন্যাল ব্যবহার করুন।
অ্যান্টনি হ্যাচকিন্স

1

পোস্ট_ডিলিট ব্যবহার করা সঠিক পথে যাওয়ার জন্য নিশ্চিত। কখনও কখনও যদিও জিনিসগুলি ভুল হতে পারে, এবং ফাইলগুলি মোছা হয় না। অবশ্যই আপনার ক্ষেত্রে এমন একগুচ্ছ পুরানো ফাইল রয়েছে যা পোস্ট_ডিলিট ব্যবহারের আগে মুছে ফেলা হয়নি। আমি একটি ফাংশন তৈরি করেছি যা যদি অবজেক্টের জন্য ফাইলগুলি মুছে দেয় তার ভিত্তিতে যদি ফাইলটির রেফারেন্স উপস্থিত থাকে না তবে অবজেক্টটি মুছুন, যদি ফাইলটির কোনও অবজেক্ট না থাকে, তবে মুছুন, এছাড়াও এটি একটি "সক্রিয়" পতাকার উপর ভিত্তি করে মুছতে পারে অবজেক্ট .. এমন কিছু যা আমি আমার বেশিরভাগ মডেলগুলিতে যুক্ত করেছি। আপনি এটি যে বস্তুগুলি যাচাই করতে চান তা দিতে হবে, অবজেক্ট ফাইলগুলির পথ, ফাইল ক্ষেত্র এবং নিষ্ক্রিয় অবজেক্টগুলি মুছতে একটি পতাকা:

def cleanup_model_objects(m_objects, model_path, file_field='image', clear_inactive=False):
    # PART 1 ------------------------- INVALID OBJECTS
    #Creates photo_file list based on photo path, takes all files there
    model_path_list = os.listdir(model_path)

    #Gets photo image path for each photo object
    model_files = list()
    invalid_files = list()
    valid_files = list()
    for obj in m_objects:

        exec("f = ntpath.basename(obj." + file_field + ".path)")  # select the appropriate file/image field

        model_files.append(f)  # Checks for valid and invalid objects (using file path)
        if f not in model_path_list:
            invalid_files.append(f)
            obj.delete()
        else:
            valid_files.append(f)

    print "Total objects", len(model_files)
    print "Valid objects:", len(valid_files)
    print "Objects without file deleted:", len(invalid_files)

    # PART 2 ------------------------- INVALID FILES
    print "Files in model file path:", len(model_path_list)

    #Checks for valid and invalid files
    invalid_files = list()
    valid_files = list()
    for f in model_path_list:
        if f not in model_files:
            invalid_files.append(f)
        else:
            valid_files.append(f)
    print "Valid files:", len(valid_files)
    print "Files without model object to delete:", len(invalid_files)

    for f in invalid_files:
        os.unlink(os.path.join(model_path, f))

    # PART 3 ------------------------- INACTIVE PHOTOS
    if clear_inactive:
        #inactive_photos = Photo.objects.filter(active=False)
        inactive_objects = m_objects.filter(active=False)
        print "Inactive Objects to Delete:", inactive_objects.count()
        for obj in inactive_objects:
            obj.delete()
    print "Done cleaning model."

এইভাবে আপনি এটি ব্যবহার করতে পারেন:

photos = Photo.objects.all()
photos_path, tail = ntpath.split(photos[0].image.path)  # Gets dir of photos path, this may be different for you
print "Photos -------------->"
cleanup_model_objects(photos, photos_path, file_field='image', clear_inactive=False)  # image file is default

0

নিশ্চিত করুন যে আপনি ফাইলের আগে " স্ব " লিখেছেন । উদাহরণস্বরূপ উপরের হতে হবে

def delete(self, *args, **kwargs):
        self.somefile.delete()

        super(MyModel, self).delete(*args, **kwargs)

আমি আমার ফাইলের আগে "স্ব "টিকে ভুলে গিয়েছি এবং এটি বিশ্বব্যাপী নেমস্পেসে যেমন দেখছিল তেমন কার্যকর হয়নি।



0

জাজানো 2.x সমাধান:

কোনও প্যাকেজ ইনস্টল করার দরকার নেই! জাজানো 2 তে এটি পরিচালনা করা খুব সহজ । আমি জ্যাঙ্গো 2 এবং এসএফটিপি স্টোরেজ ব্যবহার করে সমাধানগুলি অনুসরণ করার চেষ্টা করেছি (তবে আমি মনে করি এটি কোনও স্টোরের সাথে কাজ করবে)

প্রথমে একটি কাস্টম ম্যানেজার লিখুন । সুতরাং আপনি যদি objectsপদ্ধতিগুলি ব্যবহার করে কোনও মডেলের ফাইলগুলি মুছতে সক্ষম হতে চান তবে আপনাকে অবশ্যই একটি [কাস্টম ম্যানেজার] [3] লিখতে এবং ব্যবহার করতে হবে (এর ওভাররাইড delete()পদ্ধতিতে objects):

class CustomManager(models.Manager):
    def delete(self):
        for obj in self.get_queryset():
            obj.delete()

imageমডেলটি নিজে মুছতে এবং মুছে ফেলার আগে আপনাকে অবশ্যই মুছতে CustomManagerহবে objectsআপনার মডেলের অভ্যন্তরে প্রাথমিক :

class MyModel(models.Model):
    image = models.ImageField(upload_to='/pictures/', blank=True)
    objects = CustomManager() # add CustomManager to model
    def delete(self, using=None, keep_parents=False):

    objects = CustomManager() # just add this line of code inside of your model

    def delete(self, using=None, keep_parents=False):
        self.image.storage.delete(self.song.name)
        super().delete()

-1

আমার একটি বিশেষ কেস হতে পারে যেহেতু আমি আমার ফাইল ক্ষেত্রে গতিশীল ডিরেক্টরি নামের সাথে আপলোড_আর বিকল্পটি ব্যবহার করছি তবে আমি যে সমাধানটি পেয়েছি সেটি হল os.rmdir ব্যবহার করা।

মডেলগুলিতে:

import os

...

class Some_Model(models.Model):
     save_path = models.CharField(max_length=50)
     ...
     def delete(self, *args,**kwargs):
          os.rmdir(os.path.join(settings.MEDIA_ROOT, self.save_path)
          super(Some_Model,self).delete(*args, **kwargs)

4
এটি একটি খুব খারাপ ধারণা। আপনি কেবল একটি সম্পূর্ণ ডিরেক্টরি বনাম একটি একক ফাইল সরিয়ে ফেলবেন না (সম্ভাব্যভাবে অন্যান্য ফাইলগুলিকে প্রভাবিত করছে), আপনি আসল অবজেক্ট মুছতে ব্যর্থ হলেও এমনটি করবেন।
tbm

আপনি যদি আমার যে সমস্যাটি নিয়ে কাজ করতেন তবে এটি কোনও খারাপ ধারণা নয়;) আমি যেমনটি উল্লেখ করেছি যে আমার একটি অনন্য ব্যবহারের ঘটনা ঘটেছে যেখানে মডেলটি মুছে ফেলা হচ্ছে এটি প্যারেন্ট মডেল। বাচ্চারা মাতৃ ফোল্ডারে ফাইলগুলি লিখেছিল এবং তাই আপনি যদি পিতামাতাকে মুছে ফেলেন তবে পছন্দসই আচরণটি হ'ল ফোল্ডারের সমস্ত ফাইল মুছে ফেলা হয়েছিল। অপারেশন ক্রম যদিও ভাল পয়েন্ট। আমার কাছে সেসময় তা ঘটেনি।

কোনও শিশু মুছে ফেলা হলে আমি পৃথক শিশু ফাইলগুলি অপসারণ করতে পছন্দ করব; তারপরে আপনার যদি প্রয়োজন হয় তবে খালি থাকা অবস্থায় অভিভাবক ডিরেক্টরিটি সরাতে পারেন।
tbm

আপনি যখন শিশুদের জিনিসগুলি বের করে নিয়ে যাচ্ছেন তখন এটি উপলব্ধি করে তবে পিতামাতার অবজেক্টটি যদি নষ্ট হয়ে যায় তবে একবারে বাচ্চাদের মধ্যে পদক্ষেপ নেওয়া ক্লান্তিকর এবং অপ্রয়োজনীয় বলে মনে হয়। নির্বিশেষে, আমি এখন দেখতে পাচ্ছি যে আমি যে উত্তর দিয়েছি সেগুলি ওপি প্রশ্নের পক্ষে যথেষ্ট নির্দিষ্ট ছিল না। মন্তব্যের জন্য আপনাকে ধন্যবাদ, আপনি আমাকে এগিয়ে যাওয়ার জন্য কম ভোঁতা যন্ত্র ব্যবহার করার বিষয়ে ভাবতে বাধ্য করেছেন।
শে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.