在Django 2.0中,添加了autocomplete_fields,这很棒。
如果没有autocomplete_fields,我可以使用formfield_for_foreignkey更改ForeignKeyField的查询集。
但将两者结合起来并不起作用 - 看起来自动完成的选项列表是动态的,来自不同的网址,而不是来自当前的表单。
所以问题是 -
如何更改自动填充小部件中的查询集?
答案 0 :(得分:2)
覆盖ModelAdmin的get_search_results
方法以使用您想要的查询。您可以在get_queryset
方法中查看视图,该视图提供了用于获取查询集的自动填充字段的数据 - 此答案的来源为https://github.com/django/django/blob/master/django/contrib/admin/views/autocomplete.py#L42,但我不希望这样链接说正确的时间。
答案 1 :(得分:2)
简短:您可以在django-admin-autocomlete-all中尝试我的解决方案,或者做类似的事情。
长答案:
一个痛苦是:源外键的limit_choices_to- ..也没有实现:(
我能够对目标ModelAdmin的get_search_results()实施过滤器。
但是在这里,我们还有另一个严重的痛苦。
我们可以检查request.is_ajax and '/autocomplete/' in request.path
。
此外,我们只有request.headers ['Referer']。借助于此,我们可以将受影响的外键限制为1个模型。 但是,如果我们有2个以上的外键进入同一目标(让我们说:在同一模型实例中有两个用户角色),则我们不知道其中哪个调用ajax。
我的想法是修改网址。使用Request url失败(长时间尝试在DOM和js中找到select2元素并扩展url)。
但是我使用window.history.replaceState()修改了Referer url(即源管理页面url)取得了一些成功。我可以临时修改网址,例如/?key=author
-如果您将使用 django-admin-autocomplete-all ,该网址将始终运行,并且我可以使用其他自定义JavaScript将几乎所有内容添加到Referer网址中。特别是添加其他表单字段的当前值可能对实现动态过滤(字段的依赖性)很有用。
所以,这确实是一个hack。但是您可以尝试使用django-admin-autocomplete-all。 -有关此文档的更多信息。
答案 2 :(得分:1)
我遇到了同样的问题,当使用autocomplete_fields时,limit_choices_to没有生效,然后我找到了一种解决方案,可能对其他人也有帮助。 这是我的想法和解决方案,任何人都应该更改其使用代码。
想象一下,我们有两个模型model_A和modle_B:
我们将覆盖
的“ get_search_results”
model_A的模型管理员(因为model_B有一个foreign_key(或m2m))
就我而言,我只想将选择限制在所有
的model_A对象上
当前没有model_B连接的对象
或在将model_B的对象更新为仅限于先前的model_A对象的情况下。
所以我们走
require (
...
github.com/y version
...
)
replace github.com/y version => github.com/x your-fork-version
https://gist.github.com/mh-firouzjaah/48dceae592d4b4275fa31d37ac77ff69
答案 3 :(得分:0)
如果您将autocomplete_fields
用于{self}上的ManyToManyField
,
此示例将排除当前对象。
通过覆盖get_form
获取当前对象的ID:
field_for_autocomplete = None
def get_form(self, request, obj=None, **kwargs):
if obj:
self.field_for_autocomplete = obj.pk
return super(MyAdmin, self).get_form(request, obj, **kwargs)
接下来,覆盖get_search_results
。仅针对模型的自动完成URI修改查询集:
def get_search_results(self, request, queryset, search_term):
queryset, use_distinct = super().get_search_results(request, queryset, search_term)
# Exclude only for autocomplete
if request.path == '/admin/myapp/mymodel/autocomplete/':
queryset = queryset.exclude(field=self.field_for_autocomplete)
return queryset, use_distinct