Как динамически создавать методы свойств в моделях django?

Я создаю методы свойств для каждой модели, где атрибут модели включает ImageField или FileField. Поэтому я решил сделать абстрактную модель, где я проверяю поля в модели и если в модели есть ImageField и FileField, метод свойства создает их автоматически сам.

Обычно я добавляю '_url' к атрибуту, когда создаю метод

Ниже приведено то, что я обычно делаю

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

    @property
    def image_url(self):
        if self.image and hasattr(self.image, 'url'):
            return self.image.url


    @property
    def file_url(self):
        if self.file and hasattr(self.file, 'url'):
            return self.file.url

    ...

Ниже то, что я сделал на данный момент

class MyModel(models.Model):
    ...
    

    def __new__(cls, value):
        fields = self._meta.get_fields()
        for field in fields:
            if isinstance(field, ImageField) or isinstance(field, FileField):
                ???

Есть предложения?

Используйте миксины.

class ImageUrlMixin:

    @property
    def image_url(self):
        if self.image and hasattr(self.image, "url"):
            return self.image.url

class FileUrlMixin:

    @property
    def file_url(self):
        if self.file and hasattr(self.file, "url"):
            return self.file.url

class FileImageUrlMixin(FileUrlMixin, ImageUrlMixin):
    pass

class OnlyHasFileFieldModel(FileUrlMixin, models.Model):
    # ..model implementation

class OnlyHasImageFieldModel(ImageUrlMixin, models.Model):
    # ..model implementation

class HasBothFileAndImageFieldModel(FileImageUrlMixin, models.Model):
    # ..model implementation

Или если вы хотите поддерживать поля динамически, например, my_model.arbitrary_field_url:

class DynamicFieldUrlMixin:

    def __getattr__(self, name):
        if name.endswith("_url"):
            field_name = "".join(name.split("_")[:-1])
            field = getattr(self, field_name, None)
            if hasattr(field, "url"):
                return field.url
        raise AttributeError
Вернуться на верх