我正在使用ListView
,其中包含过滤器表单和搜索表单,如In a Django template, how to specify a dictionary key which is itself an attribute?中所述。当我提交搜索查询时,我希望它保留现有的过滤查询。
之前,我通过使用自定义过滤器<input>
添加value
从request.GET
获取的隐藏get
元素来实现此功能,该过滤器调用{{1}我的QueryDict
方法。我发现这个问题是对于get
s,例如,如果选择了多个选项,则只保留一个,因为MultipleChoiceField
方法只返回 last 价值如https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.QueryDict.get中所述。
我现在正尝试不同的方法。使用自定义过滤器get
,
relative_url
和自定义过滤器from django import template
from django.utils.http import urlencode
from django.http import QueryDict
register = template.Library()
@register.simple_tag
def relative_url(field_name, value, query_string=None):
"""
Replace the key 'field_name' in the query_string with the given value.
For example,
relative_url('guide', 1, 'q=Christine') == '?q=Christine&guide=1'
(After https://simpleisbetterthancomplex.com/snippet/2016/08/22/dealing-with-querystring-parameters.html)
"""
url = urlencode({field_name: value})
if query_string:
query_dict = QueryDict(query_string, mutable=True)
query_dict[field_name] = value
url = query_dict.urlencode()
return '?' + url
,
referer_query
我尝试按如下方式修改搜索表单:
from urllib.parse import urlparse
from django import template
register = template.Library()
@register.filter
def referer_query(request):
return urlparse(request.META.get('HTTP_REFERER')).query
当您按Enter键时,有一些Javascript代码提交表单(无需按提交按钮):
{% load relative_url %}
{% load referer_query %}
<form action="{% relative_url "q" search_form.q.value.strip|default:'' request|referer_query %}" method="get" class="left search col s6 hide-on-small-and-down" novalidate>
<div class="input-field">
<input id="search" placeholder="{{ placeholder }}"
autocomplete="off" type="search" name="q"
value="{{ search_form.q.value.strip|default:'' }}"
data-query="{{ search_form.q.value.strip|default:'' }}">
<label for="search" class="active"><i class="material-icons search-icon">search</i></label>
<i data-behavior="search-clear"
class="material-icons search-icon"
{% if not search_form.q.value %}style="display: none;"{% endif %}>close</i>
</div>
</form>
问题在于,当我通过选择过滤器并输入搜索查询来尝试此操作时,如下图所示,
当我在视图的 $(document).on('click', '[data-behavior="search-clear"]', function(e) {
$('#search').val('').parents('form').submit();
});
$(function() {
setSearchClearVisibility($('#search'));
});
$(document).on('keydown', '#search', function(e) {
var $el = $(this);
setTimeout(function() {
setSearchClearVisibility($el);
}, 10);
});
function setSearchClearVisibility(el) {
if (el.val() === '') {
$('[data-behavior="search-clear"]').hide();
} else {
$('[data-behavior="search-clear"]').show();
}
}
$(document).on('keydown', '#search', function(e) {
var $el = $(this);
setTimeout(function() {
if (e.keyCode !== 27) return;
$('#search').val('').blur();
setSearchClearVisibility($el);
if ($el.data('query') !== '') {
$('#search').parents('form').submit();
}
}, 10);
});
方法中放入调试器时,我发现get
仅包含搜索查询,而不包含过滤器查询,尽管request.GET
确实显示了过滤查询:
request.META['HTTP_REFERER']
简而言之,似乎ipdb> request.GET
<QueryDict: {'q': ['Christine']}>
ipdb> request.META.get('HTTP_REFERER')
'http://localhost:8000/dashboard/families?q=&guide=6&guide=4&next_outreach=&vip=&app='
仅由表单中的request.GET
元素决定,而不是由包含其他查询参数的表单<input>
决定。
如何让action
包含request.GET
包含的查询?
(我注意到这个blog post描述了类似问题的解决方案,但代码片段看起来有点意大利面条,我认为必须有一个更简单的方法。)
答案 0 :(得分:0)
我终于通过在filter_form
中加入隐藏search_form
来解决问题。所以在_search.html
中,<form>
代码中添加了
{% for field in filter_form %}
{{ field.as_hidden }}
{% endfor %}
这使用了字段的as_hidden
属性。