我终于能够通过使用this 帖子中列出的方法解决问题,即将查询字符串键添加到引用 URL,因为 select2 在初始化后不接受对请求 URL 的修改。
我还添加了有关正在编辑的狗的其他信息,例如它的 id 和出生年份,以进一步过滤查询集(狗不能是它自己的父母或比自己年轻的父母,母亲只能是女性......)。
//this get passes to the select2:opening event listener
function expand_ajax_location_search($, fieldId) {
if (!$) {
$ = django.jQuery;
}
var pageURL = $(location).attr("href");
var match = pageURL.match(/\/.*\/(\d+)\/change/);
return `&birth_year=${$('#id_birth_year').val()}&dog_id=${match[1]}&father_cb=${$('#father-cb').prop( "checked" )}&mother_cb=${$('#mother-cb').prop( "checked" )}`
}
最后在服务器端进行过滤具有挑战性,因为狗管理员通常由狗窝过滤,因此每个狗窝所有者只能编辑他们的狗,尽管该复选框允许他们使用其他狗窝的狗作为父母。 get_search_results 方法中的挑战是在选中该框时取消过滤查询集,这是无法完成的,因此在将其传递给 super().get_search_results 之前创建一个新查询集。
此外,基本的 get_search_results 方法似乎会遍历所有关系,即使不需要它们也会导致超过 100 个查询,因此对所有关系使用 select_related 只会产生一个查询。
def get_search_results(self, request, queryset, search_term):
if request.is_ajax and '/autocomplete/' in request.path and request.GET.get('model_name') == 'dog':
url = urllib.parse.urlparse(request.headers['Referer'])
referer = url.path
# (parse_qs results are lists)
qs = urllib.parse.parse_qs(url.query)
if request.GET.get('field_name') == 'father':
if qs.get('father_cb')[0] == 'true':
# default is filetered by kennel so need new qs
queryset = Dog.objects.select_related(
'kenn', 'img', 'father', 'mother', 'breeder').order_by('name')
queryset, use_distinct = super().get_search_results(request, queryset, search_term)
queryset = queryset.exclude(
sex='F').exclude(id=qs.get('dog_id')[0])
elif request.GET.get('field_name') == 'mother':
if qs.get('mother_cb')[0] == 'true':
# default is filetered by kennel so need new qs
queryset = Dog.objects.select_related(
'kenn', 'img', 'father', 'mother', 'breeder').order_by('name')
queryset, use_distinct = super().get_search_results(request, queryset, search_term)
queryset = queryset.exclude(
sex='M').exclude(id=qs.get('dog_id')[0])
birth_year = qs.get('birth_year')[0]
if birth_year:
queryset = queryset.exclude(birth_year__gt=birth_year)
else:
queryset, use_distinct = super().get_search_results(request, queryset, search_term)
return queryset, use_distinct