SpellTheif
SpellTheif

Reputation: 715

Django - how to pass a value from an existing HTML form to a list view

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

Upvotes: 0

Views: 541

Answers (2)

Nazkter
Nazkter

Reputation: 1110

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">

Upvotes: 0

neverwalkaloner
neverwalkaloner

Reputation: 47354

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

Upvotes: 1

Related Questions