Django : delete a post (Post model) with a OnetoMany relation with images defined in PostImage model

29 Views Asked by At

Hi have a model Post with a delete() to delete the post images which is defined as follows :

class Post(models.Model):
    uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, db_index=True)
    text = models.TextField(_('text'), max_length=settings.POST_MAX_LENGTH, blank=False, null=True,validators=post_text_validators)
    created = models.DateTimeField(editable=False, db_index=True)
    title = models.TextField(_('title'), max_length=settings.POST_TITLE_MAX_LENGTH, blank=False, null=True,

    def has_image(self):
        if hasattr(self, 'images'):

            if self.images:
                return True

        return False

    def delete(self, *args, **kwargs):
        self.delete_media()
        super(Post, self).delete(*args, **kwargs)
    
    def delete_media(self):
         posts = Post. Post.objects.all()  
         for post in posts:     
              images = post.images.all()
              for image in images:
                delete_file_field(image.image) 

I also have a PostImage model with a foreign key to Post. The model is defined as under:

class PostImage(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, null=True, related_name='images')
    image = ProcessedImageField(verbose_name=_('image'), storage=post_image_storage,
                                upload_to=upload_to_post_image_directory,
                                width_field='width',
                                height_field='height',
                                blank=False, null=True, format='JPEG', options={'quality': 80},
                                processors=[ResizeToFit(width=1024, upscale=False)])

My view calls on delete() to delete the post but it also needs to delete the images associated with it. I ran through a lot of stack posts on the best way to do it. While it gets the job done, I'm not sure whether this is the right way to do it.

Based on my reading of several posts, this is what I've understood:

1.Create an instance of Post.

posts = Post.objects.all()

2.Use the instance and loop through it using a for loop.

for post in posts:

3.For every object of the instance, assign the images.all() objects

images = post.images.all()

4.Finally,loop through all the images and delete all the images. (In my specific case)

for image in images:
                 delete_file_field(image.image)

My question is :

Why do we need to loop through the instance of the Post ?

for post in posts: 

Couldn't the above function (skipping step 2 & 3 partly )be like :

def delete_media(self):
        if self.has_image():
          posts =Post.objects.all()  
              images = posts.images.all()
              for image in images:
                delete_file_field(image.image) 

where we

1.Create an instance of Post.

posts = Post.objects.all()

2.Use the instance itself & assign the images.all() objects

images = posts.images.all()

3.Delete the post images.

for image in images:
               delete_file_field(image.image)
0

There are 0 best solutions below