django: FooSearchListView' 对象没有属性 'object_list'

django: FooSearchListView' object has no attribute 'object_list'

我正在使用 Django 3.2 和 django-taggit 1.4

我有一个这样定义的模型 Foo:

/path/to/myapp/models.py

class Foo(models.Model):
    title = models.CharField()
    story = models.CharField()
    caption = models.CharField()
    tags = TaggableManager()

我正在尝试使用 CBV 编写与一个或多个标签匹配的 Foo 对象的搜索。

这是我的代码:

/path/to/myapp/views.py

class FooSearchListView(ListView):
    model = Foo
    slug_field = 'query'
    context_object_name = 'foo_list'
    paginate_by = 3


    def post(self, request, *args, **kwargs):
    
        query_original = request.POST.get('search_terms', None)
        page = request.POST.get('page', 1)
 
        q_filter = Q()

        if query_original:
            keywords = [x.strip() for x in query_original.lower().split(',')]

            title_match = reduce(operator.or_, (Q(title__icontains=word) for word in keywords))
            story_match = reduce(operator.or_, (Q(story__icontains=word) for word in keywords))
            captions_match = reduce(operator.or_, (Q(caption__icontains=word) for word in keywords))             
            tags_match = reduce(operator.or_, (Q(tags__name__icontains=word) for word in keywords))

            q_filter = title_match | story_match | captions_match | tags_match 
    
        foos = Foo.objects.filter(q_filter).distinct().order_by('-date_added')


        context = self.get_context_data(*args, **kwargs)       
        context['keywords'] = keywords

        return render(request, 'search_items.html', context=context)

/path/to/my/app/urls.py

urlpatterns = [
    # ...         
    path('search/', FooSearchListView.as_view(), name='foo-search'),     
    # ...

]

我不喜欢我构建代码的方式,因为我无法覆盖 get_queryset() 等方法,所有逻辑都在 post() 方法中- 因为搜索是故意只在 POSTS 上进行的。

上面的代码有两个问题:

  1. 当我尝试在浏览器中进行搜索时,收到错误消息:FooSearchListView' object has no attribute 'object_list'

  2. 分页不起作用

如何解决这些问题?

[[编辑]]

Traceback (most recent call last):
  File "/path/to/my/project/env/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/path/to/my/project/env/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/path/to/my/project/env/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/path/to/my/project/env/lib/python3.8/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/path/to/my/project/foo/views.py", line 185, in post
    context = self.get_context_data(*args, **kwargs)
  File "/path/to/my/project/foo/views.py", line 159, in get_context_data
    context = super().get_context_data(*args, **kwargs)
  File "/path/to/my/project/env/lib/python3.8/site-packages/django/views/generic/list.py", line 115, in get_context_data
    queryset = object_list if object_list is not None else self.object_list

Exception Type: AttributeError at /foo/search/
Exception Value: 'FoooSearchListView' object has no attribute 'object_list'

ListView 继承自 MultipleObjectMixinMultipleObjectMixin 覆盖方法 get_context_data 并具有以下 line [GitHub]:

queryset = object_list if object_list is not None else self.object_list

问题是您已经为您的视图覆盖了 post 并在没有设置 self.object_list 的情况下调用 get_context_dataget 方法在其实现中设置)因此你得到错误。因此,您需要在 post 方法中设置它的值:

self.object_list = self.get_queryset()
context = self.get_context_data(*args, **kwargs)

或者在进一步查看您的实现之后,您似乎想要执行一些过滤并将其用作您的查询集。如果是这样,您可以尝试如下操作:

class FooSearchListView(ListView):
    model = Foo
    slug_field = 'query'
    context_object_name = 'foo_list'
    paginate_by = 3
    
    def filter_queryset(self, queryset=None):
        if queryset is None:
            queryset = self.get_queryset()
        query_original = self.request.POST.get('search_terms', None)
        page = self.request.POST.get('page', 1)
        q_filter = Q()

        if query_original:
            keywords = [x.strip() for x in query_original.lower().split(',')]

            title_match = reduce(operator.or_, (Q(title__icontains=word) for word in keywords))
            story_match = reduce(operator.or_, (Q(story__icontains=word) for word in keywords))
            captions_match = reduce(operator.or_, (Q(caption__icontains=word) for word in keywords))             
            tags_match = reduce(operator.or_, (Q(tags__name__icontains=word) for word in keywords))

            q_filter = title_match | story_match | captions_match | tags_match
        return queryset.filter(q_filter).distinct().order_by('-date_added')
    
    def post(self, request, *args, **kwargs):
        self.object_list = self.filter_queryset(queryset=self.get_queryset())
        context = self.get_context_data(*args, **kwargs)       
        context['keywords'] = keywords

        return render(request, 'search_items.html', context=context)