[英]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.