Запрос на удаление альбома в приложении Django
Суть кейса: Есть картинки(сущность в бд). Также есть альбомы, которые могут содержать картинки. По факту картинка может быть : либо в одном альбоме, либо в нескольких, либо ни в одном(связь mtm проще говоря). Когда приходит запрос на удаление альбома, нужно проверить, есть ли в нем картинка, которая содержится в других альбома. Если картинка находится только в данном альбоме - удаляем альбом и картинку. Если нет - картинку оставляем. Код:
#album.models
class AlbumManager(Manager):
# def annotate_count_pictures(self, queryset):
# queryset.prefetch_related('album_pictures')
def get_pictures(self, id=None):
queryset = AlbumPicture.objects.select_related('picture').values('picture_id').annotate(count=Count('picture_id'))
return queryset.all()
# Create your models here.
class Album(models.Model):
name = models.CharField(max_length=200, blank=False, null=False)
user = models.ForeignKey(User, blank=False, null=False, on_delete=models.CASCADE)
date_created = models.DateTimeField(default=datetime.now())
objects = AlbumManager()
class Meta:
db_table = 'album'
def delete(self, using=None, keep_parents=False):
return super().delete(using, keep_parents)
class AlbumPicture(models.Model):
picture = models.ForeignKey('picture.Picture', related_name='picture_album', blank=False, null=True,
on_delete=models.CASCADE)
album = models.ForeignKey(Album, related_name='album_picture', blank=False, null=True, on_delete=models.CASCADE)
class Meta:
db_table = 'album_picture'
#picture.models
class Picture(models.Model):
name = models.CharField(max_length=255, blank=False)
user = models.ForeignKey(User, related_name='user_picture', null=False, on_delete=models.CASCADE)
image = models.ImageField(upload_to='media')
date_of_published = models.DateTimeField(blank=False, default=datetime.now())
likes = models.PositiveIntegerField(null=False, blank=False, default=0)
album = models.ManyToManyField(Album, through=AlbumPicture, related_name='album_pictures', blank=True)
category = models.ForeignKey('PictureCategory', blank=False, null=False, on_delete=models.DO_NOTHING)
objects = PictureManager()
def get_absolute_url(self):
return reverse('retrieve-update-destroy-picture', kwargs={'id': self.id})
def __str__(self):
return self.name
class Meta:
ordering = ['date_of_published']
db_table = 'picture'
Код сервиса(вызывается в хуке perform_destroy -> instance - это обьект модели Album):
def delete_album_with_images(instance):
pictures = Album.objects.get_pictures(instance.id)
picture_to_delete_ids = []
for p in pictures:
if p.get('count') == 1:
picture_id = p.get('picture_id')
picture_to_delete_ids.append(picture_id)
Picture.objects.filter(id__in=picture_to_delete_ids).delete()
instance.delete()
Я пытался писать запросы с group by(используя values), однако там возвращаются обьекты ввиде словаря, так что потом приходится делать еще один запрос на каждую картинку. Какие есть идеи по поводу оптимизации данного запроса?