Руслан Волшебник
Руслан Волшебник24 січня 2020 р. 09:52

Как лучше реализовать модели в бд?

database, Django

Здравствуйте. Снова я здесь со своими вопросами)
Как лучше реализовать структуру моделей для файлов?
Хочу хранить файлы в отдельной модели или моделях (это уже как вы мне подскажите).
Ну так вот, какая схема лучше подойдёт?
1. Делать несколько моделей, которые имеют отношения OneToOne с моделью File.
2. Или же одну модель File, где будет поле file_type.

Мне чутьё подсказывает, что 1-ый вариант лучше использовать, если пригодятся какие-то дополнительные поля для каждого типа файла, а во всех остальных 2-ой.

1.

class File(models.Model):
    pass

class AbstractFile(models.Model):
    filename = models.FileField(upload_to='files')
    file = models.OneToOneField(File, on_delete=models.CASCADE, primary_key=True)
    date = models.DateTimeField(auto_now_add=True, null=True, blank=True)

    class Meta:
        abstract = True

    def delete(self, *args, **kwargs):
        self.file.delete()
        return super(self.__class__, self).delete(*args, **kwargs)

class Image(AbstractFile):
    filename = models.ImageField(upload_to='images')

class Document(AbstractFile):
    pass

2.

class File(models.Model):
    DOCUMENT = 0
    IMAGE = 1
    AUDIO = 2
    VIDEO = 3

    FILE_TYPE_CHOICES = (
        (DOCUMENT, 'Документ'),
        (IMAGE, 'Изображение'),
        (AUDIO, 'Видео'),
        (VIDEO, 'Аудио')
    )
    file_type = models.PositiveSmallIntegerField(choices=FILE_TYPE_CHOICES, default=DOCUMENT)
    file = models.FileField(upload_to='files')

И ещё... Как можно сделать, чтобы в 1-ом варианте можно было к File связать только с одним объектом. Допустим два объекта Image я не могу связать через OneToOne с File, это понятно, но можно 1 Image и 1 Document. Как сделать, чтобы можно было связать только с одной либо Image, либо Document...?

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

6
Илья Чичак
  • 24 січня 2020 р. 10:32

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

    Ну получается тогда, что если мне пока не нужны дополнительные поля для каждого типа файла, то лучше использовать одну модель File.
    Я просто думал на всякий случай сделать, может пригодится. Видимо, раз сейчас надобности нет, сделаю одну модель File.

      Илья Чичак
      • 24 січня 2020 р. 10:48
      • (відредаговано)

      я думаю, если это вдруг отвечает вашим хотелкам, вы можете сделать 2 разные формы для этого, в одной из которых сделать поле ImageField (со всеми вытекающими проверками), а в другой оставить FileField. Но в обоих случаях все складывать в одну модель с типом поля FileField.
      Но в любом случае, не зная предметную область, очень сложно дать какой-то вменяемый ответ. Лучше всего всегда начинать с описания, что вы хотите сделать - так будет проще=)

      кстати, из интересного - не обязательно указывать OneToOne на модель=)

      class File(models.Model):
          pass
      
      class ImageFile(File): # тут будет связь один к одному на модель File
          pass
      
      class AbstractFile(models.Model):
          class Meta:
              abstract = True
      
      class ImageFileInheritance(AbstractFile): # а тут будет уже наследование
          pass
      
      

      если хотите наследоваться - надо указать в File.Meta.abstract = True

        Руслан Волшебник
        • 24 січня 2020 р. 11:34
        • (відредаговано)

        Хорошо. Вот подробности)
        Делаю бота в telegram. Telegram каждому файлу загружаемому на их сервера даёт некий file_id. Мне нужно записывать это file_id в бд. И следующий раз не файл отправлять пользователю, а этот file_id.

        Сейчас у меня есть модель Image. И есть FileID, которая хранит file_id каждой картинки.
        Также у меня есть модель TelegramBot, так как ботов целых 2 штуки. Связи с этим в модель FileID добилось поле bot, которая хранит ссылку на бота. Так сделано потому что у одного файла может быть разный file_id, в зависимости от того в какой бот был загружен файл.

        Вот модель FileID для наглядности

        class FileID(models.Model):
            name = models.CharField(max_length=100)
            image = models.ForeignKey(Image, on_delete=models.CASCADE, related_name='file_ids')
            bot = models.ForeignKey(TelegramBot, on_delete=models.CASCADE, related_name='file_ids')
        
            def __str__(self):
                return self.name
        

        В поле name хранится тот самый file_id.

        Всё это время я работал только с картинками, но теперь нужно добавить и другие файлы.
        Поэтому решил сделать отдельную модель File, ссылку на которую добавлю в FileID вместо Image.

          Ещё появилась мысля сделать, отдельно модели Image, Document, Video, Audio. А в FileID использовать GenericForeignKey.
          Или сделать так:

          class File(models.Model):
              image = ForeignKey(Image, null=True, blank=True)
              video = ForeignKey(Video, null=True, blank=True)
              audio = ForeignKey(Audio, null=True, blank=True)
              document = ForeignKey(Document, null=True, blank=True)
          

          А при сохранении разрешить только один тип файла.

          Я уже, честно говоря, запутался.

            Илья Чичак
            • 27 січня 2020 р. 03:17

            а почему бы не сделать одну модель, например Attachement со всеми этими полями, и в зависимости от действия пользователя, например, "добавить документ", "добавить картинку" и т.д. класть все это в разные поля?

              Коментарі

              Only authorized users can post comments.
              Please, Log in or Sign up
              AD

              C++ - Тест 004. Указатели, Массивы и Циклы

              • Результат:50бали,
              • Рейтинг балів-4
              m
              • molni99
              • 26 жовтня 2024 р. 01:37

              C++ - Тест 004. Указатели, Массивы и Циклы

              • Результат:80бали,
              • Рейтинг балів4
              m
              • molni99
              • 26 жовтня 2024 р. 01:29

              C++ - Тест 004. Указатели, Массивы и Циклы

              • Результат:20бали,
              • Рейтинг балів-10
              Останні коментарі
              ИМ
              Игорь Максимов22 листопада 2024 р. 11:51
              Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
              Evgenii Legotckoi
              Evgenii Legotckoi31 жовтня 2024 р. 14:37
              Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
              A
              ALO1ZE19 жовтня 2024 р. 08:19
              Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
              ИМ
              Игорь Максимов05 жовтня 2024 р. 07:51
              Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
              d
              dblas505 липня 2024 р. 11:02
              QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
              Тепер обговоріть на форумі
              Evgenii Legotckoi
              Evgenii Legotckoi24 червня 2024 р. 15:11
              добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
              t
              tonypeachey115 листопада 2024 р. 06:04
              google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
              NSProject
              NSProject04 червня 2022 р. 03:49
              Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
              9
              9Anonim25 жовтня 2024 р. 09:10
              Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

              Слідкуйте за нами в соціальних мережах