Max Loyd
Max Loyd

Reputation: 418

Django redirect after search using a queryset

When I click search on the homepage, I want it to take that query set e.g (http://127.0.0.1:8000/?q=car) and then use the same url, but in the search view. I have tried searching around but couldn't find anything that was working.

Views:

class IndexView(ListView):
    model = Post
    # queryset = Post.objects.filter(live=True)
    template_name = "public/index.html"

    def get_queryset(self):
       queryset = super().get_queryset().filter(live=True)
       query = self.request.GET.get("q")
       if query:
        queryset = queryset.filter(title__icontains=query)
       return redirect(reverse('search-view'), queryset)

    def get_context_data(self, **kwargs):
        context = super(IndexView, self).get_context_data(**kwargs)
        context['queryset'] = self.get_queryset()
        context['category'] = Category.objects.all()
        return context

URLS:

urlpatterns = [
    path('', views.IndexView.as_view(), name="index-view"),

    path('post/create/', views.PostCreateView.as_view(), name="post-create"),
    path('post/<slug>/update/', views.PostUpdateView.as_view(), name="post-update"),
    path('post/<slug>/', views.PostDetailView.as_view(), name="post-detail"),

    path('category/', views.CategoryView.as_view(), name="category"),
    path('category/<int:pk>/', views.CategoryDetailView.as_view(), name="category-detail"),

    path('search/', views.SearchListView.as_view(), name="search-view")
]

I have tried doing it using a redirect and reverse but it is not working at all, it is actually giving me an error for using slice on a forloop that is using queryset. 'slice' object has no attribute 'lower'

I have 2 templates/views. When I click search on the homepage, I want it to carry on over to the search view and then run the search query on there.

Thanks.

Upvotes: 0

Views: 1477

Answers (1)

Johan
Johan

Reputation: 3611

I think you're mixing up the logic a bit on where to do the actual query. You should't do the actual query search in the IndexView that is meant for the SearchListView.

From the information that's available right now (without the SearchListView) I'd say you could do a redirect and pass the parameter onto the query url and let the view in SearchListView decide what to do with the information:

def get_queryset(self):
    queryset = super().get_queryset().filter(live=True)
    query = self.request.GET.get("q")
    if query:
        # Fetch the url for the search-view
        base_url = reverse('search-view')
        # Make the search query url encoded
        query_string =  urlencode({'q': query})
        # Tie it together with the url
        url = '{}?{}'.format(base_url, query_string)
        # Fire away
        return redirect(url)
    return redirect(reverse('search-view'), queryset)

Source: Some code taken from The Ultimate Guide to Django Redirects by Daniel Hepper

Upvotes: 2

Related Questions