Home > Enterprise >  Filter Option with class based view django
Filter Option with class based view django

Time:02-01

I need to filter by a topic/category in my posts; but I think it is dificult to do this with class based views.

I have: (this works)

  • models.py
class Post(models.Model):
    class Topic(models.TextChoices):
        DEV = 'DEVELOPMENT', ('Development')
        LIFE = 'LIFE', ('Life')
        OTHER = 'OTHER', ('Other')
        __empty__ = ('-Unknown-')

    topic = models.CharField(max_length=15, choices=Topic.choices, default=Topic.__empty__)

  • views.py
def filter_view(request, topic):
    posts = Post.objects.filter(
        topic__contains=topic
    ).order_by('-pub_date')
    return render(request, 'blog/posts.html', {'posts': posts})
  • urls.py
urlpatterns = [
    path('', IndexView.as_view(), name='blog'),
    path('posts/', PostsView.as_view(), name='posts'),
    path('posts/<slug:slug>-<int:id>/', PostDetailView.as_view(), name='post_detail'),
    path('posts/topic=<topic>/', filter_view, name='topic'),
]
  • templates/posts.html
<div >
    <span >Filter by:</span>
    <a href="{% url 'blog:topic' 'Development' %}" metho="GET" >Development</a>
    <a href="{% url 'blog:topic' 'Life' %}" >Life</a>
    <a href="{% url 'blog:topic' 'Other' %}" >Other</a>
</div>

**But I wanna to use a class based view **

  • views.py
lass TopicView(generic.ListView):
    template_name = 'blog/posts.html'
    context_object_name = 'posts'

    def get_queryset(self):
        topic = self.request.GET.get('topic')
        return posts = Post.objects.filter(
            topic__contains=topic
        ).order_by('-pub_date')
  • urls.py
urlpatterns = [
    # Other code
    path('posts/topic=<topic>/', TopicView.as_view(), name='topic'),
]

Error:

Internal Server Error: /blog/posts/topic=Development/
Traceback (most recent call last):
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\views\generic\base.py", line 69, in view
    return self.dispatch(request, *args, **kwargs)
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\views\generic\base.py", line 101, in dispatch
    return handler(request, *args, **kwargs)
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\views\generic\list.py", line 142, in get
    self.object_list = self.get_queryset()
  File "D:\projects\Python3\python3.10.1\Django\website\blog\views.py", line 36, in get_queryset
    posts = Post.objects.filter(
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\db\models\query.py", line 974, in filter
    return self._filter_or_exclude(False, args, kwargs)
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\db\models\query.py", line 992, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, args, kwargs)
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\db\models\query.py", line 999, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\db\models\sql\query.py", line 1375, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\db\models\sql\query.py", line 1396, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\db\models\sql\query.py", line 1329, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "D:\projects\Python3\python3.10.1\Django\venv\lib\site-packages\django\db\models\sql\query.py", line 1185, in build_lookup
    raise ValueError("Cannot use None as a query value")
ValueError: Cannot use None as a query value

I think that code can't find the topic name so can't search for it; Can I solve this or better should I leave it like this?

CodePudding user response:

You don't get the URL parameter with self.request.GET, but with self.kwargs, so:

class TopicView(generic.ListView):
    template_name = 'blog/posts.html'
    context_object_name = 'posts'

    def get_queryset(self):
        return Post.objects.filter(
            topic__contains=self.kwargs['topic']
        ).order_by('-pub_date')
  •  Tags:  
  • Related