Проблема фильтрации динамического 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