I am trying to filter a model’s objects dynamically depending on what the user selects in a form. The form allows selecting from two dropdown lists. Selecting from either dropdown is optional. If the user does not select anything and clicks Submit, there will be an empty search results page. I believe I didn’t do some things correctly. When I extract data from form.cleaned_data
, when field_1
is only selected by the user, its value is assigned to field_2
and field_1
ends up being assigned the string “field_1”. Same for when only field_2
is selected. Why is it switching the value assignment and assigning the string name of each to itself?
Output
self.kwargs = {"field_1": field_2_value, "field_2": "field_2"}
self.kwargs = {"field_1": "field_1", "field_2": field_1_value}
However, when the user selects a value from each dropdown list, the values are properly assigned.
Here is my code:
views.py
class MyDataView(generic.ListView):
template_name = "my_data/my_data.html"
context_object_name = "my_data_list"
def get_context_data(self, **kwargs):
context = super(MyDataView, self).get_context_data(**kwargs)
context["form"] = SearchForm
return context
def get_queryset(self):
# Update and create data in the MyData model
populate_my_data()
return MyData.objects.all()
class MyDataSearcher(FormView):
form_class = SearchForm
def form_valid(self, form):
field_1 = form.cleaned_data.get("field_1 ", "")
field_2 = form.cleaned_data.get("field_2 ", "")
kwargs = {}
if field_1 :
kwargs["field_1 "] = field_1
if field_2 :
kwargs["field_2 "] = field_2
# Redirect to the search results page
return HttpResponseRedirect(reverse("my_data:search_results_view", kwargs=kwargs))
class SearchResultsView(generic.ListView):
model = MyData
template_name = "my_data/search_results.html"
def get_context_data(self, **kwargs):
context = super(SearchResultsView, self).get_context_data(**kwargs)
my_data_list = []
field_1= self.kwargs.get("field_1", "")
field_2 = self.kwargs.get("field_2 ", "")
context["no_result"] = ""
filters = {}
if filters:
try:
my_data_list = MyData.objects.filter(**filters)
except (KeyError, MyData.DoesNotExist):
return render(
self.request,
"my_data/table_viewer.html",
{
"error_message": "No data filters selected"
}
)
else:
context["no_result"] = "Please select from the lists"
context["my_data_list"] = my_data_list
context["field_1"] = field_1
context["field_2"] = field_2
# NOTE: For debugging
context["kwargs"] = self.kwargs
return context
forms.py
from django import forms
from .populate_data import PopulateChoices
POPULATED_CHOICES = PopulateChoices()
class SearchForm(forms.Form):
field_1 = forms.ChoiceField(
choices=POPULATED_CHOICES.field_1_choices,
label="Field 1",
required=False
)
field_2 = forms.ChoiceField(
choices=POPULATED_CHOICES.field_2_choices,
label="Field 2",
required=False
)
urls.py
urlpatterns = [
path("table_viewer/", views.MyDataView.as_view(), name="my_data_view"),
path("table_viewer/search/", views.MyDataSearcher.as_view(), name="my_data_searcher"),
path("search_results/<str:field_1>/<str:field_2>/", views.SearchResultsView.as_view(), name="search_results_view"),
path("search_results/field_1/<str:field_1>/", views.SearchResultsView.as_view(), name="search_results_view"),
path("search_results/<str:field_2>/field_2/", views.SearchResultsView.as_view(), name="search_results_view"),
path("search_results/", views.SearchResultsView.as_view(), name="search_results_view")
]
forms.py
<form action={% url "my_data:my_data_searcher" %} method="post">
{% csrf_token %}
{{ form }}
<input name="submitted" type="submit" value="Search">
</form>
I’m expecting that field_1
would only be in the self.kwargs
when only field_1
is selected.
self.kwargs = {"field_2": field_2_value}
And when field_2
is only selected, it should only be in self.kwargs
.
self.kwargs = {"field_1": field_1_value}
Angel L is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.