ИМ
Жел. 22, 2018, 6:44 Т.Ж.

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

django

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

  1. class Serial(models.Model):
  2. class Meta:
  3. db_table = 'serial'
  4. verbose_name = 'Сериал'
  5. verbose_name_plural = 'Сериалы'
  6.  
  7. name = models.CharField(verbose_name='Название', max_length=200)
  8. orig_name = models.CharField(verbose_name='Оригинальное название', max_length=200, blank=True)
  9. poster = models.ImageField(
  10. # upload_to=curry(upload_to_media, prefix='posters'),
  11. upload_to=upload_to_media,
  12. blank=True,
  13. verbose_name='Постер'
  14. )
  15. category = models.ForeignKey(CategorySerial, on_delete=models.CASCADE, verbose_name='Категория', null=True, blank=True)
  16. year = models.DateField(verbose_name='Дата выхода', default='2000-01-01')
  17. country = models.CharField(verbose_name='Страна', max_length=300, default='Неизвестно')
  18. translate = models.CharField(verbose_name='Перевод', max_length=300, default='Русский')
  19. create = models.DateTimeField(verbose_name='Дата публикации', default=timezone.now)
  20. update = models.DateTimeField(verbose_name='Дата обновления', default=timezone.now)
  21. description = models.TextField(verbose_name='Описание')
  22. moder = models.BooleanField(verbose_name='Модерация', default=False)
  23. votes = GenericRelation(LikeDislike, related_query_name='serials')
  24.  
  25. def public(self):
  26. self.date = timezone.now()
  27. self.save()
  28.  
  29. def __str__(self):
  30. return self.name
  31.  
  32. def get_absolute_url(self):
  33. return reverse('serial:serial_detail', args=[self.id])
  34.  
  35. def get_bookmark_count(self):
  36. return self.bookmarkserial_set.all().count()
  37.  
  38.  
  39. class Playlist(models.Model):
  40. class Meta:
  41. db_table = 'playlist'
  42. verbose_name = 'Плейлист'
  43. verbose_name_plural = 'Плейлисты'
  44. name = models.CharField(max_length=250, verbose_name='Имя плейлиста')
  45. serial = models.ForeignKey(Serial, on_delete=models.CASCADE)
  46.  
  47. def __str__(self):
  48. return self.name
  49.  
  50.  
  51.  
  52. class Seria(models.Model):
  53. class Meta:
  54. db_table = 'seria'
  55. verbose_name = 'Серия'
  56. verbose_name_plural = 'Серии'
  57.  
  58. playlist = models.ForeignKey(Playlist, on_delete=models.CASCADE)
  59. serial = models.ForeignKey(Serial, on_delete=models.CASCADE)
  60. video = models.FileField(
  61. # upload_to=curry(upload_to_media, prefix='movies'),
  62. upload_to=upload_to_media,
  63. verbose_name='Видео'
  64. )

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

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

2

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

12
Evgenii Legotckoi
  • Жел. 22, 2018, 5:06 Т.Қ.

Добрый день.

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

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

  1. class SeriaAdminForm(forms.ModelForm):
  2.  
  3. def __init__(self, *args, **kwargs):
  4. super().__init__(*args, **kwargs)
  5.  
  6. try:
  7. self.fields['playlist'].queryset = self.instance.serial.playlist_set.all()
  8. except Playlist.DoesNotExist:
  9. pass
  10.  
  11.  
  12. class SeriaAdmin(PostAdmin):
  13. form = SeriaAdminForm
  14.  
  15.  
  16. admin.site.register(Seria, SeriaAdmin)

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

    ИМ
    • Жел. 22, 2018, 7:22 Т.Қ.

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

    1. serial.models.Seria.serial.RelatedObjectDoesNotExist: Seria has no serial.
      Evgenii Legotckoi
      • Жел. 22, 2018, 7:31 Т.Қ.
      • (өңделген)

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

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

      1. class SeriaAdminForm(forms.ModelForm):
      2.  
      3. def __init__(self, *args, **kwargs):
      4. super().__init__(*args, **kwargs)
      5.  
      6. try:
      7. self.fields['playlist'].queryset = self.instance.serial.playlist_set.all()
      8. except Playlist.DoesNotExist:
      9. pass
      10. except Seria.serial.RelatedObjectDoesNotExist:
      11. pass

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

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

        ИМ
        • Жел. 22, 2018, 8:24 Т.Қ.

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

          Evgenii Legotckoi
          • Жел. 22, 2018, 8:32 Т.Қ.

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

          1. class SeriaAdminForm(forms.ModelForm):
          2.  
          3. def __init__(self, *args, **kwargs):
          4. super().__init__(*args, **kwargs)
          5.  
          6. try:
          7. self.fields['playlist'].queryset = self.instance.serial.playlist_set.all()
          8. except Playlist.DoesNotExist:
          9. pass
          10. except Seria.serial.RelatedObjectDoesNotExist:
          11. self.fields['playlist'].queryset = Playlist.objects.none()

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

            ИМ
            • Жел. 22, 2018, 8:39 Т.Қ.

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

              Evgenii Legotckoi
              • Жел. 22, 2018, 8:54 Т.Қ.
              • Жауап шешім ретінде белгіленді.

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

              1. class MyFormSet(BaseInlineFormSet):
              2. def get_form_kwargs(self, index):
              3. kwargs = super().get_form_kwargs(index)
              4. kwargs['parent_object'] = self.instance
              5. return kwargs
              6.  
              7.  
              8. class MyForm(forms.ModelForm):
              9. def __init__(self, *args, parent_object, **kwargs):
              10. self.parent_object = parent_object
              11. super(MyForm, self).__init__(*args, **kwargs)
              12.  
              13. try:
              14. self.fields['playlist'].queryset = parent_object.playlist_set.all()
              15. except Playlist.DoesNotExist:
              16. pass
              17.  
              18.  
              19. class MyChildInline(admin.TabularInline):
              20. formset = MyFormSet
              21. form = MyForm

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

                ИМ
                • Жел. 22, 2018, 9:49 Т.Қ.
                • (өңделген)

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

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

                  ИМ
                  • Жел. 22, 2018, 9:59 Т.Қ.

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

                    Evgenii Legotckoi
                    • Жел. 23, 2018, 1:01 Т.Ж.

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

                      ИМ
                      • Жел. 23, 2018, 1:05 Т.Ж.

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

                        Evgenii Legotckoi
                        • Жел. 23, 2018, 1:10 Т.Ж.

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

                          Пікірлер

                          Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
                          Кіріңіз немесе Тіркеліңіз