I have a form with multiple select
inputs, as below:
<form method="POST" action="{% url 'solution_product_list' %}">
{% csrf_token %}
{# main select div: usage or model? #}
<div >
<h2 >انتخاب بر اساس:</h2>
<select required aria-label="Select usage or model" id="usage_model_select" onchange="set_usage_or_model_dic()">
<option selected>----</option>
<option value="usage">کاربرد</option>
<option value="model">مدل</option>
</select>
</div>
{# usage or model select div #}
<div >
{# usage select div #}
<div id="usage_div">
<h2 >انتخاب کاربرد:</h2>
<select required aria-label="Select usage"
name="usage_select" onchange="set_sub_usage_list()" id="usage_select_id">
<option selected>----</option>
{% for usage in usage_queryset %}
<option value="{{ usage.id }}">{{ usage.usage_name_fa }}</option>
{% endfor %}
</select>
</div>
{# model select div #}
<div id="model_div">
<h2 >انتخاب مدل:</h2>
<select required aria-label="Select model"
name="model_select" onchange="set_pump_type_list()" id="model_select_id">
<option selected>----</option>
{% for model in main_model_queryset %}
<option value="{{ model.id }}">{{ model.model_name_fa }}</option>
{% endfor %}
</select>
</div>
</div>
{# select sub_usage or pump_type div #}
<div >
{# sub_usage select div #}
<div id="sub_usage_div">
<h2 >انتخاب کاربرد جزئی:</h2>
<select required aria-label="Select sub_usage" name="sub_usage_select">
<option selected>همهی کابردهای جزئی</option>
{% for sub_usage in sub_usage_queryset %}
<option value="{{ sub_usage.id }}">{{ sub_usage.sub_usage_name_fa }}</option>
{% endfor %}
</select>
</div>
{# model select div #}
<div id="pump_type_div">
<h2 >انتخاب تیپ:</h2>
<select aria-label="Select pump_type" name="pump_type_select">
<option selected>همهی تیپهای این مدل</option>
{% for pump_type in pump_type_queryset %}
<option value="{{ pump_type.id }}">{{ pump_type.type_name }}</option>
{% endfor %}
</select>
</div>
</div>
<div>
<input type="submit" value="مرحله بعدی" id="submit" >
</div>
</form>
As you can see, the action of my form is "{% url 'solution_product_list' %}"
, but I'd like to send the selected value (from any select inputs that has been selected) to this action url, as it would be {% url 'solution_product_list' selected_value %}
. I did some searches and came accross to these questions which suggested using redirect
:
Django form action url dynamic
How to send selected option value in form action in django
Django : HTML form action directing to view (or url?) with 2 arguments
Dynamic URL routing from html form within action in Django
But none the above helped me, or maybe I could not understand the solutions there. Can anyone please help me on this matter?
Also I have a messy view
for this page, as below:
def solution_product_list(request):
product_list_queryset = None
sub_usage_list = []
pump_type_list = []
if request.method == "POST":
if request.POST["usage_select"] != "----":
usage_select = request.POST["usage_select"]
product_list_queryset = Product.objects.filter(usage__id=usage_select)
sub_usage_list = SubUsage.objects.filter(usage__id=usage_select)
if request.POST["sub_usage_select"] != "همهی کابردهای جزئی":
sub_usage_select = request.POST["sub_usage_select"]
product_list_queryset = Product.objects.filter(
sub_usage__id=sub_usage_select
)
elif request.POST["model_select"] != "----":
model_select = request.POST["model_select"]
product_list_queryset = Product.objects.filter(main_model__id=model_select)
pump_type_list = PumpType.objects.filter(
main_model__id=model_select
)
if request.POST["pump_type_select"] != "همهی تیپهای این مدل":
pump_type_select = request.POST["pump_type_select"]
product_list_queryset = Product.objects.filter(
pump_type__id=pump_type_select
)
elif request.POST["head"] and request.POST["flow"]:
flow = float(request.POST["flow"])
head = float(request.POST["head"])
head_flow_list_main = get_head_flow_list(product_list_queryset)
product_list = return_filtered_products(
head_flow_list_main, head, flow
)
product_list_queryset = Product.objects.filter(id__in=product_list)
page = request.GET.get("page", 1)
paginator = Paginator(product_list_queryset, 10)
try:
product_list = paginator.page(page)
except PageNotAnInteger:
product_list = paginator.page(1)
except EmptyPage:
product_list = paginator.page(paginator.num_pages)
queryset_dictionary = get_common_queryset()
page_context = {
"product_list": product_list_queryset,
"sub_usage_queryset": sub_usage_list,
"pump_type_queryset": pump_type_list,
}
print(product_list_queryset)
context = {
**queryset_dictionary,
**page_context,
}
return render(request, "solutions/second_stage_select.html", context)
I'm relatively new to Django, so if you can give me any advice on better code formatting or writing, your notes will be most appreciated.
CodePudding user response:
Although it's better to use form widgets to manage this situations but another solution is:
selected_lang = request.POST.get('lang_txt')
So your code in view could be as follow:
usage_select = request.POST.get('usage_select')
And in your html template you can do as follow to maintain and display previos selected options using your context:
<option value="span_to_eng" {% if data.selected_lang == 'span_to_eng' %}selected{% endif %}>Spanish To English</option>
CodePudding user response:
The reason is, you set the values of the context when there is a post
method, but you do not return an i.e. HttpResponse
or redirect
object.
let's solve your problem with less code, you can get the idea:
views.py
:
from django.shortcuts import render
from django.shortcuts import redirect
def first_stage(request):
extra_context_from_view = ["opt1", "opt2", "opt3"]
context = {
"extra_context_from_view": extra_context_from_view,
"previously_saved_val_db": "opt2",
}
if request.method == "POST":
if request.POST["first_stage"]:
context = {"forward_to_second_stage": request.POST["first_stage"]}
# in the case of redirect un comment two below line
# and you should comment the second_stage render
# request.session['redirected_context'] = {'redirected': 'test'}
# return redirect("second_stage")
return render(request, "pages/second_stage.html", context)
return render(request, "pages/first_stage.html", context)
def second_stage(request):
context = {"second_view": "from_second_view"}
return render(request, "pages/second_stage.html", context)
first_stage.html
{% comment %}
remove this line if it is not necessary
{% if val == previously_saved_val_db %}selected{% endif %}
it is just an example to show you how to dynamically set the
value attribute of a tag in HTML.
{% endcomment %}
<form method="POST" action="{% url 'first_stage' %}">
{% csrf_token %}
<h2 >Some Header</h2>
<select name="first_stage">
<option selected>----</option>
{% for val in extra_context_from_view %}
<option value="{{ val }}"
{% if val == previously_saved_val_db %}selected{% endif %}>{{ val }}</option>
{% endfor %}
</select>
<input type="submit" value="submit" id="submit">
</form>
second_stage.html
<p> Normal view after post at the same URL (view)</p>
<h1> YOUR SELECT OPTION: {{ forward_to_second_stage }} </h1>
<p> Redirected version at another URL (view)</p>
{% comment %}
pay atention you probably get session value even you do not use
the redirect method
{% endcomment %}
{{ request.session.redirected_context }}
<br>
{{ second_view }}
urls.py
:
urlpatterns = [
path("first-stage/", views.first_stage, name="first_stage"),
path("second-stage/", views.second_stage, name="second_stage"),
]
if you use the return render(request, "pages/second_stage.html", context)
the url will not change and the process will be performed at the current view, but witha different template.
P.S:
- Post your question with a minimal reproducible example.
- You can debug your code by printing inside the template.
- You can see what values are passed from the view to the template and vice versa.
- Use something like
IntegerChoices
orTextChoices
in your model and - Use them inside the view for comparison. - Use
{% trans %}
like tag in template for the labels.