簡體   English   中英

Django - 一個頁面上有兩個forms,提交任何一個表單時如何維護URL參數?

[英]Django - Two forms on one page, how can I maintain URL parameters when either form is submitted?

我正在構建一個包含膳食列表的應用程序,其中每頓膳食都有各種過濾器、價格和評級。

過濾器就像標簽; 用戶可以 select 多個,頁面僅顯示具有所選過濾器的餐點。

價格和評級是整數,用戶可以按價格或評級排序,即對餐點進行排序(最便宜 -> 價格最貴,最高 -> 評級最低)。

我在Django里面建了兩台forms,一台做過濾,一台做排序,都各自獨立工作。 但是,假設我提交了按價格排序的排序表單; 當我這樣做時,它確實按價格排序,但它刪除了我之前提交的所有過濾器。

以下是與此問題相關的重要代碼片段:

視圖.py

def meals(request):
    meal_list = Meal.objects.all()
    tags = Tag.objects.all()
    reviews = Review.objects.all()
    filter_form = FilterForm(request.GET or None)
    sorting_form = SortingForm(request.GET or None)
    sort = ""
    active_filters = []

    if filter_form.is_valid():
        tags = filter_form.cleaned_data.get('tags')
        for tag in tags:
            meal_list = meal_list.filter(tags__name=tag)
            active_filters.append(tag)

    if sorting_form.is_valid():
        sort = sorting_form.cleaned_data.get('sort')
        if sort == "price":
            meal_list = meal_list.order_by('price')
        else:
            meal_list = meal_list.order_by('-rating')

    paginator = Paginator(meal_list, 8)
    page_number = request.GET.get('page')
    meals_on_page = paginator.get_page(page_number)

    context = {"meal_list": meal_list,
               "distances": distances,
               "tags": tags,
               "reviews": reviews,
               "active_filters": active_filters,
               "meals_on_page": meals_on_page,
               "filter_form": filter_form,
               "sorting_form": sorting_form,
               }
    return render(request, 'meals/meals.html', context)

forms.py

from django import forms

# Tag is the model for the filters, it is just a ManyToManyField that contains a name attribute
from .models import Tag


class FilterForm(forms.Form):
    tags = forms.ModelMultipleChoiceField(
        queryset=Tag.objects.all(), widget=forms.CheckboxSelectMultiple)


class SortingForm(forms.Form):
    SORT_CHOICES = [
        ('price', 'Price'),
        ('rating', 'Rating'),
    ]
    sort = forms.ChoiceField(choices=SORT_CHOICES, widget=forms.Select)

膳食.html

  <form method="get">
    {% for field in filter_form %}
        {{ field.as_widget }} {{ field.label_tag }}
    {% endfor %}
    <input type="submit" value="Filter">
  </form>


  <form method="get">
    {% for field in sorting_form %}
        {{ field.as_widget }}
    {% endfor %}
    <input type="submit" value="Sort">
  </form>

遺憾的是,我花了太長時間試圖解決這個問題,而我得到的最接近的是使用get_copy = request.GET.copy()然后嘗試在提交表單后手動將 URL 參數添加回 URL 的末尾。 但是,我使用它的方法似乎都不起作用。

先謝謝您的幫助!

在您的 Django 視圖中,您可以使用請求對象的 GET 屬性訪問當前的 URL 參數。 要在提交任一表單時維護這些參數,您可以將它們包含在模板的表單操作屬性中。

例如,在您的模板中,您可以更新表單操作屬性以包含當前的 URL 參數,如下所示:

<form method="get" action="{% url 'meals' %}?{{ request.GET.urlencode }}">

這會將 append 和當前的 URL 參數傳遞給表單操作,因此當提交表單時,當前參數將包含在請求中。

在您看來,您可以使用 request.GET 字典訪問這些參數。 在呈現模板之前,您可以使用這些參數對查詢集進行相應的過濾和排序。

注意:您還應該在處理表單數據之前檢查 forms 是否有效,以避免出現意外行為。

此外,您可以使用 Django 的 forms.HiddenInput() 將 forms 上的當前參數作為隱藏字段包含在內,這樣您就不需要更新表單的 action 屬性。

在浸泡(太多)更多小時后,我最終解決了這個問題。

我這樣做的方法是構建我自己的參數字典,然后將這些參數作為隱藏輸入傳遞給 forms。

下面是添加的代碼:

視圖.py

get_copy = request.GET.copy()
parameters = get_copy.urlencode()
get_copy.pop('page', None)
param_list = parameters.split("&")
param_dict = defaultdict(list)
for param in param_list:
    try:
        key, value = param.split("=")
    except ValueError:
        # Handle the case where there's no "=" in the parameter string
        key = param
        value = ""
    if key == "tags":
        param_dict[key].append(int(value))
    else:
        param_dict[key].append(value)
# Django requires me to turn dictionary to items here, rather than in the template
param_dict_items = param_dict.items()

膳食.html

<form method="get" action="{% url 'meals' %}?{{ request.GET.urlencode }}">
{% for field in filter_form %}
    {{ field.as_widget }} {{ field.label_tag }}
{% endfor %}

{% for key, value_list in param_dict_items %}
  {% if key != 'tags' %}
    {% for value in value_list %}
      <input type="hidden" name="{{ key }}" value="{{ value }}">
    {% endfor %}
  {% endif %}
{% endfor %}
<input type="submit" value="Filter">
<form method="get" action="{% url 'meals' %}">
{% for field in sorting_form %}
    {{ field.as_widget }}
{% endfor %}

{% for key, value_list in param_dict_items %}
  {% if key != 'sort' %}
    {% for value in value_list %}
      <input type="hidden" name="{{ key }}" value="{{ value }}">
    {% endfor %}
  {% endif %}
{% endfor %}
<input type="submit" value="Sort">

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM