Mfreeman
Mfreeman

Reputation: 3958

How to Pass option from search into url

Currently i have a search that returns models matching the input. My goal is to add a dropdown to this search and pass that into the url for the use of separate views in one template.

So my search form would look like this

index.html

<form method="GET" action = "{% url 'app:search' %}">
 <input  name="q" type="text" placeholder="search by Key or Name"/>
 <select name = "category">
     <option value = "1"> Category 1</option>
     <option value = "2"> Category 2</option>
     <option value = "all"> All</option>
 </select>
  <input  type="submit" value="Search"/>
    </form>

I need my urls to look something like this

urls.py

app_name = 'app'
urlpatterns = [
        path('login/index/', views.IndexView.as_view()),
        path('login/index/<category option here>/search', views.SearchView.as_view(), name="search"),
        path('login/index/<category option here>/<slug:key>', views.ModelView.as_view(), name="detail"),  
    ]

I am able to grab the key and push that to the url on the search results page no problem like this

search.html

<ul>
    {% for x in results %}
    <li><a href = "{% url 'app:detail' x.key %}">{{x.name}}</a></li>
    {% endfor %}
</ul>

And able to grab the key by using a get function like so in my views

def get(self, request, *args, **kwargs):
    self.q = self.kwargs['key']
    return super().get(request, *args, **kwargs)

But since category isnt part of this model's schema i cannot use this same approach(theres a complicated reason as to why it isnt)

OVERALL

I need to carry on the category option selected from the IndexView into the ModelView and be able to use that in my templates to create different pages like i have below, and hopefully use a GET function in my view to access the category and return context that gives me the category

<% if category == "1" %>
   <h1> CATEGORY 1 </h1>

<% elseif category == "2" %>
   <h2> CATEGORY 2 </h1>

EDIT: views.py

class SearchView(LoginRequiredMixin, TemplateView):
    template_name = 'app/search.html'

    def get(self, request, *args, **kwargs):
        q = request.GET.get('q','')
        for term in list(set(q.split())):
            self.results = Model1.objects.filter(Q(name__icontains= term) | Q(key__icontains=term))
        return super().get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(SearchView, self).get_context_data(**kwargs)
        context['results'] = self.results
        return context

Upvotes: 0

Views: 71

Answers (1)

trixn
trixn

Reputation: 16344

If you want to have the searched category available in the ModelView this would be a way to achive that:

Extend your SearchView by passing the searched category into the context too:

class SearchView(LoginRequiredMixin, TemplateView):
    # ...

    def get_context_data(self, **kwargs):
        context = super(SearchView, self).get_context_data(**kwargs)
        context['results'] = self.results
        context['searched_category'] = self.request.GET.get('q')
        return context

Then you can use that in search.html to encode it into the url:

<ul>
    {% for x in results %}
        <li><a href = "{% url 'app:detail' searched_category x.key %}">{{x.name}}</a></li>
    {% endfor %}
</ul>

Adapt your urls like that:

app_name = 'app'
urlpatterns = [
    path('login/index/', views.IndexView.as_view()),
    path('login/index/search', views.SearchView.as_view(), name="search"),
    path('login/index/<str:searched_category>/<slug:key>', views.ModelView.as_view(), name="detail"),  
]

And now you can access the category in your ModelViel via self.kwargs:

class ModelView(...):
    @property
    def searched_category(self):
        return self.kwargs.get('searched_category')

    # use it in any view method with 'self.searched_category'

Upvotes: 1

Related Questions