Руслан Волшебник
Jan. 24, 2020, 8:52 p.m.

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

database, Django

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

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

1.

  1. class File(models.Model):
  2. pass
  3.  
  4. class AbstractFile(models.Model):
  5. filename = models.FileField(upload_to='files')
  6. file = models.OneToOneField(File, on_delete=models.CASCADE, primary_key=True)
  7. date = models.DateTimeField(auto_now_add=True, null=True, blank=True)
  8.  
  9. class Meta:
  10. abstract = True
  11.  
  12. def delete(self, *args, **kwargs):
  13. self.file.delete()
  14. return super(self.__class__, self).delete(*args, **kwargs)
  15.  
  16. class Image(AbstractFile):
  17. filename = models.ImageField(upload_to='images')
  18.  
  19. class Document(AbstractFile):
  20. pass

2.

  1. class File(models.Model):
  2. DOCUMENT = 0
  3. IMAGE = 1
  4. AUDIO = 2
  5. VIDEO = 3
  6.  
  7. FILE_TYPE_CHOICES = (
  8. (DOCUMENT, 'Документ'),
  9. (IMAGE, 'Изображение'),
  10. (AUDIO, 'Видео'),
  11. (VIDEO, 'Аудио')
  12. )
  13. file_type = models.PositiveSmallIntegerField(choices=FILE_TYPE_CHOICES, default=DOCUMENT)
  14. file = models.FileField(upload_to='files')

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

2

Do you like it? Share on social networks!

6
Илья Чичак
  • Jan. 24, 2020, 9:32 p.m.

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

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

      Илья Чичак
      • Jan. 24, 2020, 9:48 p.m.
      • (edited)

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

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

      1. class File(models.Model):
      2. pass
      3.  
      4. class ImageFile(File): # тут будет связь один к одному на модель File
      5. pass
      6.  
      7. class AbstractFile(models.Model):
      8. class Meta:
      9. abstract = True
      10.  
      11. class ImageFileInheritance(AbstractFile): # а тут будет уже наследование
      12. pass
      13.  

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

        Руслан Волшебник
        • Jan. 24, 2020, 10:34 p.m.
        • (edited)

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

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

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

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

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

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

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

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

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

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

            Илья Чичак
            • Jan. 27, 2020, 2:17 p.m.

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

              Comments

              Only authorized users can post comments.
              Please, Log in or Sign up
              • Last comments
              • AK
                April 1, 2025, 11:41 a.m.
                Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
              • Evgenii Legotckoi
                March 9, 2025, 9:02 p.m.
                К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
              • VP
                March 9, 2025, 4:14 p.m.
                Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
              • ИМ
                Nov. 22, 2024, 9:51 p.m.
                Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
              • Evgenii Legotckoi
                Oct. 31, 2024, 11:37 p.m.
                Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup