0

I have an existing HTML form (text field + button) but have no idea how to pass an input value to a list view.

Update:

book/home.html:

<form class="form-inline my-2 my-lg-0" method="get" action="{% url 'book:search' %}">{% csrf_token %}
    <input style="font-size: 12px; width: 200px" class="form-control mr-sm-2" name="search" type="search" placeholder="Book Name" aria-label="Search">
    <button class="btn btn-outline-primary my-2 my-sm-0" type="submit">Search</button>
</form>

book/models:

class Book(models.Model):

    title = models.CharField(max_length=191, unique=True)

    slug = models.SlugField(unique=True, null=True, allow_unicode=True)

    pub_date = models.DateField()

    ............

book/views:

class SearchResultView(generic.ListView):
    template_name = 'book/search.html'
    model = Book
    paginate_by = 10

    def get_queryset(self):
        queryset = super().get_queryset()
        search = self.request.GET.get('search')
        if search:
            queryset.filter(title__icontains=search)
        return queryset


class BookDetailView(generic.DetailView):
    template_name = 'book/detail.html'
    model = Book

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

book/urls:

app_name = 'book'
urlpatterns = [
    path('', views.HomePageView.as_view(), name='home'),
    path('<slug:slug>/', views.BookDetailView.as_view(), name='detail'),
    path('search/', views.SearchResultView.as_view(), name='search')
]

book/templates/search.html (just for testing):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1> here we go </h1>
</body>
</html>

Error on browser: enter image description here

2 Answers 2

1

First of all for search functionality you can use GET request instead of POST. To send form data to the specific view use action attribute. Also you need to add name attribute for input element:

<form class="form-inline my-2 my-lg-0" method="get" action="{% url 'view_urlname' %}">
    <input style="font-size: 12px; width: 200px" class="form-control mr-sm-2" type="search" placeholder="Book Name" name="search" aria-label="Search">
    <button class="btn btn-outline-primary my-2 my-sm-0" type="submit">Search</button>
</form>

To fetch form data in the view use self.request.GET:

class SearchResultView(generic.ListView):
    template_name = 'book/search.html'
    model = Book
    paginate_by = 100

    def get_queryset(self):
        queryset = super().get_queryset()
        search = self.request.GET.get('search')
        if search:
            queryset.filter(filedname_contains=search)
        return queryset
Sign up to request clarification or add additional context in comments.

7 Comments

yeah that makes sense. but it is saying Page not found (404) No book found matching the query. The filed in book is called 'title', so I wrote queryset.filter(title__contains='search'). I tried single underscore and double underscore, they both didn't work.
And that error Raised by: book.views.BookDetailView. It was raised by another view, but that view is working fine.
@Jinx try icontains. Also it should be search not 'search'. Without quotes: queryset.filter(title__icontains=search).
still not working. And in book/urls - path('search/', views.SearchResultView.as_view(), name='search'), just tell you in case.
@jinx swap detail view and search view in urlpattern. Detail view's pattern is too common and triggered by /search/ url.
|
0

If you are trying to create a custom queryset and show only the filter queryset instead of the full one, you can overwrite the get_queryset() function and get the form input by accessing self.request.POST.

def get_queryset(self):
    if self.request.method == 'POST':
        book_name = self.request.POST.get('book_name', '')
        return Book.objects.filter(name=book_name)  # i'm assuming that in your Book model the name field if called 'name'

Then, you just have to be sure that the input has a name like this:

<input name="book_name" style="font-size: 12px; width: 200px" class="form-control mr-sm-2" type="search" placeholder="Book Name" aria-label="Search">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.