ИМ
Игорь Максимов21 декабря 2018 г. 19:44

Подскажите по фильтрации объектов в админ-панели

django

Доброго времени суток. У меня ситуация следующая, имею 3 модели которые принадлежат один ко многим:

class Serial(models.Model):
    class Meta:
        db_table = 'serial'
        verbose_name = 'Сериал'
        verbose_name_plural = 'Сериалы'

    name = models.CharField(verbose_name='Название', max_length=200)
    orig_name = models.CharField(verbose_name='Оригинальное название', max_length=200, blank=True)
    poster = models.ImageField(
        # upload_to=curry(upload_to_media, prefix='posters'),
        upload_to=upload_to_media,
        blank=True,
        verbose_name='Постер'
    )
    category = models.ForeignKey(CategorySerial, on_delete=models.CASCADE, verbose_name='Категория', null=True, blank=True)
    year = models.DateField(verbose_name='Дата выхода', default='2000-01-01')
    country = models.CharField(verbose_name='Страна', max_length=300, default='Неизвестно')
    translate = models.CharField(verbose_name='Перевод', max_length=300, default='Русский')
    create = models.DateTimeField(verbose_name='Дата публикации', default=timezone.now)
    update = models.DateTimeField(verbose_name='Дата обновления', default=timezone.now)
    description = models.TextField(verbose_name='Описание')
    moder = models.BooleanField(verbose_name='Модерация', default=False)
    votes = GenericRelation(LikeDislike, related_query_name='serials')

    def public(self):
        self.date = timezone.now()
        self.save()

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('serial:serial_detail', args=[self.id])

    def get_bookmark_count(self):
        return self.bookmarkserial_set.all().count()


class Playlist(models.Model):
    class Meta:
        db_table = 'playlist'
        verbose_name = 'Плейлист'
        verbose_name_plural = 'Плейлисты'
    name = models.CharField(max_length=250, verbose_name='Имя плейлиста')
    serial = models.ForeignKey(Serial, on_delete=models.CASCADE)

    def __str__(self):
        return self.name



class Seria(models.Model):
    class Meta:
        db_table = 'seria'
        verbose_name = 'Серия'
        verbose_name_plural = 'Серии'

    playlist = models.ForeignKey(Playlist, on_delete=models.CASCADE)
    serial = models.ForeignKey(Serial, on_delete=models.CASCADE)
    video = models.FileField(
        # upload_to=curry(upload_to_media, prefix='movies'),
        upload_to=upload_to_media,
        verbose_name='Видео'
    )

В админ панели ситуация следующая:
Создал я плейлист в одной сериале, и добавляя видео в другом сериале у меня плейлисты с предыдущего

Вопрос заключается в следующем: как отображать плейлисты только принадлежащие к определенному сериалу а не весь список плейлистов.

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

Вам это нравится? Поделитесь в социальных сетях!

12
Evgenii Legotckoi
  • 22 декабря 2018 г. 6:06

Добрый день.

Это делается через установку кастомной формы для model.Admin

Смысл в том, чтобы в соответствующем поле отфильтровать только те серии, или плейлисты, которые отностятся к данном сериалу

class SeriaAdminForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        try:
            self.fields['playlist'].queryset = self.instance.serial.playlist_set.all()
        except Playlist.DoesNotExist:
            pass


class SeriaAdmin(PostAdmin):
    form = SeriaAdminForm


admin.site.register(Seria, SeriaAdmin)

По идее так должно работать правильно.

    ИМ
    • 22 декабря 2018 г. 8:22

    Так то оно работает, но я использую Inline. В inline не хочет, пишет:

    serial.models.Seria.serial.RelatedObjectDoesNotExist: Seria has no serial.
    
      Evgenii Legotckoi
      • 22 декабря 2018 г. 8:31
      • (ред.)

      Ну, полагаю, что весь прикол в том, что здесь просто не обработано это исключение. Поскольку при создании нового объекта там никакой объект не создан.

      А если так? Нужно тогда обработать это исключение и всё

      class SeriaAdminForm(forms.ModelForm):
      
          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
      
              try:
                  self.fields['playlist'].queryset = self.instance.serial.playlist_set.all()
              except Playlist.DoesNotExist:
                  pass
              except Seria.serial.RelatedObjectDoesNotExist:
                  pass
      

      Там скорее всего понадобится сначала установить сериал, сохранить все объекты, а потом уже появится возможность выбора плейлистов.

      Дальше я бы покопал в сторону обновления queryset плейлистов в случае изменения внешнего ключа на сериал.

        ИМ
        • 22 декабря 2018 г. 9:24

        Я ошибся. Вышеуказанные формы не работают.
        А с добавлением except Seria.serial.RelatedObjectDoesNotExist: пропускает ошибку, и в выпадающем списке все плейлисты.

          Evgenii Legotckoi
          • 22 декабря 2018 г. 9:32

          Возможно, тогда стоит установить пустой queryset в том случае если нет внешнего ключа на сериал.

          class SeriaAdminForm(forms.ModelForm):
          
              def __init__(self, *args, **kwargs):
                  super().__init__(*args, **kwargs)
          
                  try:
                      self.fields['playlist'].queryset = self.instance.serial.playlist_set.all()
                  except Playlist.DoesNotExist:
                      pass
                  except Seria.serial.RelatedObjectDoesNotExist:
                      self.fields['playlist'].queryset = Playlist.objects.none()
          

          В любом случае, пока не установлен ключ на сериал, то по логике вы не можете установить какой-либо плейлист туда

            ИМ
            • 22 декабря 2018 г. 9:39

            А так в выпадающем списке ничего нет(

              Evgenii Legotckoi
              • 22 декабря 2018 г. 9:54
              • Ответ был помечен как решение.

              Нужно тогда усложнять код, поскольку серия ещё не создана, то нужно сначала получить внешний ключ на парента

              class MyFormSet(BaseInlineFormSet):
                  def get_form_kwargs(self, index):
                      kwargs = super().get_form_kwargs(index)
                      kwargs['parent_object'] = self.instance
                      return kwargs
              
              
              class MyForm(forms.ModelForm):
                  def __init__(self, *args, parent_object, **kwargs):
                      self.parent_object = parent_object
                      super(MyForm, self).__init__(*args, **kwargs)
              
                     try:
                          self.fields['playlist'].queryset = parent_object.playlist_set.all()
                      except Playlist.DoesNotExist:
                          pass
              
              
              class MyChildInline(admin.TabularInline):
                  formset = MyFormSet
                  form = MyForm
              

              что-то вроде такого должно получиться.

                ИМ
                • 22 декабря 2018 г. 10:49
                • (ред.)

                Вместо parent_object подставлять serial?

                UPD: У меня отступы сдвинулись.

                  ИМ
                  • 22 декабря 2018 г. 10:59

                  Так все работает. Спасибо вам огромное. Учусь с вами потихоньку.

                    Evgenii Legotckoi
                    • 22 декабря 2018 г. 14:01

                    Отступы? какие отступы? в админке? это уже детали, которые просто нужно будет дооправить в дальнейшем.

                      ИМ
                      • 22 декабря 2018 г. 14:05

                      У меня try сьехал влево, сначала не за метил и получал ошибки. Почудилось мне что нужно свои переменные подставлять))

                        Evgenii Legotckoi
                        • 22 декабря 2018 г. 14:10

                        А копировали просто с моего комментария. Там действительно съехал на один пробел. Ну я редактировал сразу в форме комментария текст.

                          Комментарии

                          Только авторизованные пользователи могут публиковать комментарии.
                          Пожалуйста, авторизуйтесь или зарегистрируйтесь
                          Дмитрий

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

                          • Результат:60баллов,
                          • Очки рейтинга-1
                          Дмитрий

                          C++ - Тест 003. Условия и циклы

                          • Результат:92баллов,
                          • Очки рейтинга8
                          d
                          • dsfs
                          • 26 апреля 2024 г. 14:56

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

                          • Результат:80баллов,
                          • Очки рейтинга4
                          Последние комментарии
                          k
                          kmssr9 февраля 2024 г. 5:43
                          Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                          АК
                          Анатолий Кононенко5 февраля 2024 г. 12:50
                          Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                          EVA
                          EVA25 декабря 2023 г. 21:30
                          Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
                          J
                          JonnyJo25 декабря 2023 г. 19:38
                          Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
                          G
                          Gvozdik19 декабря 2023 г. 8:01
                          Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
                          Сейчас обсуждают на форуме
                          G
                          George137 мая 2024 г. 10:27
                          добавить qlineseries в функции в функции: "GPlotter::addSeries(QString title, QVector &arr)" я вызываю метод setChart(...), я в конструктор передал адрес на QChartView элемент
                          BlinCT
                          BlinCT5 мая 2024 г. 15:46
                          Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
                          PS
                          Peter Son4 мая 2024 г. 3:57
                          Best Indian Food Restaurant In Cincinnati OH Ready to embark on a gastronomic journey like no other? Join us at App india restaurant and discover why we're renowned as the Best Indian Food Restaurant In Cincinnati OH . Whether y…
                          Evgenii Legotckoi
                          Evgenii Legotckoi3 мая 2024 г. 0:07
                          Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.
                          IscanderChe
                          IscanderChe30 апреля 2024 г. 14:22
                          Во Flask рендер шаблона не передаётся в браузер Доброе утро! Имеется вот такой шаблон: <!doctype html><html> <head> <title>{{ title }}</title> <link rel="stylesheet" href="{{ url_…

                          Следите за нами в социальных сетях