Как реализовать ограничения на загрузку медиафайлов и использовать модели в Django API для крупной системы управления файлами недвижимости?

Я создаю крупную систему управления файлами недвижимости, используя Django API. Я создал отдельное приложение для обработки мультимедиа, и в моей модели я хочу ввести следующие ограничения:

Одно показанное изображение Галерея, содержащая не более 10 изображений Не более 2 загруженных видео, каждое с изображением обложки Не более 2 музыкальных файлов Не более 2 PDF-файлов Для этого я использовал сквозную модель для подключения медиамодели к основной модели, такой как модель "листинг" или "проект".

Мой вопрос заключается в следующем: Должны ли эти ограничения на загрузку обрабатываться в сериализаторе Django или есть лучший подход? Является ли это лучшим способом подключения моделей, особенно когда основные модели могут иметь несколько внешних ключей? Я беспокоюсь о производительности и масштабируемости.

Поскольку скорость имеет решающее значение, а мне нужно подключать мультимедиа к моделям в нескольких приложениях, каков был бы наиболее эффективный способ реализации этих ограничений?

Заранее спасибо!

мой код :

Model.py


from django.db import models
from django.core.validators import FileExtensionValidator
import os
from django.utils.translation import gettext_lazy as _
import uuid
from django.core.exceptions import ValidationError
from src.core.models.base import BaseModel

def upload_media_path(instance, filename):
    ext = filename.split('.')[-1].lower()
    return f"{instance.content_type.model}/{instance.media_type}/{uuid.uuid4()}.{ext}"

ALLOWED_EXTENSIONS = {
    "image": ["jpg", "webp", "png", "svg",],
    "video": ["mp4",],
    "pdf": ["pdf"],
    "audio": ["mp3",],
}

class Media(BaseModel):
    MEDIA_TYPE_CHOICES = [
        ('image', _('Image')),
        ('video', _('Video')),
        ('pdf', _('PDF')),
        ('audio', _('Audio')),
    ]
    media_type = models.CharField(choices=MEDIA_TYPE_CHOICES,
        max_length=10,
        verbose_name=_("Media Type"), help_text=_("Alternative text for the image for accessibility and SEO purposes.")
    )
    file = models.FileField(upload_to=upload_media_path,
        validators=[
            FileExtensionValidator(allowed_extensions=sum(ALLOWED_EXTENSIONS.values(), []))
        ],
        verbose_name=_("File"), help_text=_("Alternative text for the image for accessibility and SEO purposes.")
    )
    thumbnail = models.ImageField(upload_to='thumbnail_images/',
        null=True, blank=True,
        verbose_name=_("Thumbnail"), help_text=_("تصویر شاخص برای مدیا")
    )
    video_cover = models.ImageField(upload_to='video_cover/',
        null=True, blank=True,
        verbose_name=_("Video Cover"), help_text=_("تصویر کاور برای ویدئو (در صورت نیاز)")
    )
    title = models.CharField(
        max_length=100, null=True, blank=True,
        verbose_name=_("Title")
    )
    alt_text = models.CharField(
        max_length=255, blank=True,
        verbose_name=_("ALT Text"), help_text=_("Alternative text for the image for accessibility and SEO purposes.")
    )

    def clean(self):
        if self.file and self.file.size > 10 * 1024 * 1024:
            raise ValidationError(_("حجم فایل نباید بیشتر از 10 مگابایت باشد!"))

    def save(self, *args, **kwargs):
        self.clean()
        super().save(*args, **kwargs)

    def delete(self, *args, **kwargs):
        if self.file:
            file_path = self.file.path
            if os.path.isfile(file_path):
                os.remove(file_path)
        super().delete(*args, **kwargs)

    class Meta:
        db_table = 'media'
        indexes = [
            models.Index(fields=['media_type']),
            models.Index(fields=['thumbnail']),
        ]
        verbose_name = _("Media")
        verbose_name_plural = _("Media")



Портфолио Media.py

from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext_lazy as _
from src.core.models.base import BaseModel
from src.media.models.media import Media
from src.portfolio.models.portfolio import Portfolio


class PortfolioMedia(BaseModel):
    portfolio = models.ForeignKey(Portfolio, on_delete=models.CASCADE,
        related_name='portfolio_medias',
        verbose_name = _("Portfolio"),
        help_text = _("The portfolio to which this media belongs.")
    )
    media = models.ForeignKey(Media, on_delete=models.CASCADE,
        related_name='portfolio_links',
        verbose_name = _("Media"),
        help_text = _("The media file associated with the portfolio.")
    )
    order = models.PositiveIntegerField(
        default=0,
        verbose_name=_("Order"),
        help_text=_("The order of this media item in the portfolio.")
    )

    def clean(self):
        if self.is_featured and self.media.media_type == 'image':
            featured_count = (PortfolioMedia.objects.filter(portfolio=self.portfolio,is_featured=True,media__media_type='image')
            .exclude(id=self.id).count())
            if featured_count >= 1:
                raise ValidationError(_("Only one featured image is allowed per portfolio."))

        if self.media.media_type == 'video':
            video_count = (PortfolioMedia.objects.filter(portfolio=self.portfolio,media__media_type='video')
            .exclude(id=self.id).count())
            if video_count >= 3:
                raise ValidationError(_("A maximum of 3 videos are allowed per portfolio."))
            if not getattr(self.media, 'cover_image', None):
                raise ValidationError(_("Each video must have an associated cover image."))

    def save(self, *args, **kwargs):
        self.clean()
        super().save(*args, **kwargs)

    class Meta:
        ordering = ['order']
        db_table = 'portfolio_media'
        verbose_name = _("Portfolio Media")
        verbose_name_plural = _("Portfolio Media")
        indexes = [
            models.Index(fields=['portfolio']),
            models.Index(fields=['media']),
            models.Index(fields=['order']),
        ]

    def __str__(self):
        return f"{self.portfolio} - {self.media}"

Please tell me the best solution
Вернуться на верх