Home > Net >  Django: Send a SELECT value inside form action url
Django: Send a SELECT value inside form action url

Time:12-24

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 or TextChoices in your model and - Use them inside the view for comparison.
  • Use {% trans %} like tag in template for the labels.
  • Related