Проблема фильтрации динамического ListView в Django

Я работаю над своим первым самостоятельным проектом с Django и столкнулся с проблемой, которую не решили никакие поиски и чтение похожих постов на SO.

Я пытаюсь отфильтровать галерею изображений по их категориям, чтобы при нажатии пользователем на картинку открывалась страница, показывающая все изображения с той же категорией. Надеюсь, в конечном продукте будет использоваться HTMX, но я пытаюсь и терплю неудачу, пытаясь реализовать это с помощью обычных представлений Django.

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

Я следовал документации по динамической фильтрации CBV. Я переписал get_queryset, передавая строку категории в kwargs, и я переписал get_context_data, чтобы я мог передать slug в шаблон.

Я получаю ошибку Reverse for 'select' with arguments '('',)' not found. 1 pattern(s) tried: ['select/(?P<slug>[-a-zA-Z0-9_]+)\\Z'], поэтому я считаю, что проблема в моем шаблоне/URLconf.

Модели. Медиа с FK для его Категории

class Category(models.Model):
    title = models.CharField(max_length=200, null=True)
    slug = AutoSlugField(populate_from='title')`

class Media(models.Model):
    timestamp = models.DateTimeField()
    image = models.ImageField(upload_to="media")
    url = models.URLField()
    order = models.IntegerField(default=0)
    visable = models.BooleanField(default=True)
    categories = models.ForeignKey(Category, on_delete=models.CASCADE, null=True, blank=True)

Виды, IndexView - вся галерея, SelectView - изображения по категориям

class IndexView(ListView):

    template_name = "main/index.html"
    model = Media

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context ['main_images'] = Media.objects.filter(visable=True)
        return context


class SelectView(ListView):

    template_name = "main/select.html"
    model = Media

    def get_queryset(self):
        self.category = get_object_or_404(Category, title=self.kwargs['slug'])
        return Media.objects.filter(categories__title=self.category)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['slug'] = self.category
        return context

URLconf с select в качестве соответствующего шаблона.

app_name = "main"

urlpatterns = [
    path("", views.IndexView.as_view(), name="home"),
    path("about", views.AboutView.as_view(), name="about"),
    path("contact", views.ContactView.as_view(), name="contact"),
    path("select/<slug:slug>", views.SelectView.as_view(), name="select"),
]

В шаблоне галереи у меня есть цикл for для отображения IndexView. Я думаю, что проблема в Href (который я хочу передать в SelectView). Я передаю slug в {% url %}, но думаю, что это должен быть image.categories__slug? Я пробовал это, но это все еще не работает. Я в тупике


{% for image in main_images %}
        <div class="cbp-item web-design print"> 
<a href="{% url "main:select" slug %}" class="cbp-caption cbp-singlePageInline">

<div class="cbp-caption-defaultWrap"> <img src="{{ MEDIA_URL }} {{ image.image.url }}"alt=""> </div>
{% endfor %}

Большое спасибо.

Я думаю, что вы хотите получить доступ к полю slug на поле image.categories для каждой итерации.

{% for image in main_images %}
     ... 
     <a href="{% url 'main:select' image.cateogries.slug %}" class="cbp-caption cbp-singlePageInline">
     ...
{% endfor %}

В дополнение к этому, я бы рекомендовал вам сделать поиск принимающего slug вместо title в модели Category. Например, если вы сохраните I love this day в качестве title, то в поле slug будет I-love-this-day.

Что у вас есть:

def get_queryset(self):
    self.category = get_object_or_404(Category, title=self.kwargs['slug'])
    return Media.objects.filter(categories__title=self.category)

title=self.kwargs['slug'] не найдет title, если вы передаете I-love-this-day в качестве slug. Я бы предложил использовать slug=self.kwargs['slug']. Смотрите следующие обновления:

def get_queryset(self):
    # Also, the self keyword is not needed here either -> self.category
    category = get_object_or_404(Category, slug=self.kwargs['slug'])  # updated
    return Media.objects.filter(categories__title=category.title)  # updated

Дополнительно, я вижу, что вы передаете slug как значение через переменную context внутри SelectView... Я предлагаю вам передать объект категории явно через переменную context в шаблон, где вы сможете получить доступ к полям из вашего шаблона, если это необходимо.

В пределах get_context_data():

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    # context['slug'] = self.category
    context['category'] = get_object_or_404(Category, slug=self.kwargs['slug'])
    return context
Вернуться на верх