Python 如何在modelform中使用autocompleteselect小部件
我知道Django 2.0中有一个新特性,即ModelAdmin中的AutocompleteSelect小部件。 我试图在自定义模型表单中使用它,但失败了 像这样试过Python 如何在modelform中使用autocompleteselect小部件,python,django,modelform,Python,Django,Modelform,我知道Django 2.0中有一个新特性,即ModelAdmin中的AutocompleteSelect小部件。 我试图在自定义模型表单中使用它,但失败了 像这样试过 #unit is the foreign key to the incident class AccountForm(forms.ModelForm): class Meta: model = Invoice ... ... widgets = {
#unit is the foreign key to the incident
class AccountForm(forms.ModelForm):
class Meta:
model = Invoice
...
...
widgets = { 'incident':widgets.AutocompleteSelect(Invoice._meta.get_field('incident').remote_field, admin.site)
}
...
希望有人能帮助我。
谢谢自动完成选择小部件在管理站点之外无法工作。 如果您在管理站点中使用AccountForm,则可以使用以下代码:
class AccountForm(forms.ModelForm):
...
incident = forms.ModelChoiceField(
queryset= Unit.objects.all(),
widget=AutocompleteSelect(Invoice.incident.field.remote_field, admin.site),
)
...
class Meta:
model = Invoice
fields = [
'incident',
...
]
@admin.register(Invoice)
class InvoiceAdmin(admin.ModelAdmin):
form = AccountForm
AutocompleteSelect
有两个必需的参数,rel
和admin\u站点
。rel
用于提取用于从ForeignKey或ManyToManyField上的属性查询数据并与之相关的模型。因为我想在一个实际上不是外键的字段上使用它,所以我需要重写一些东西以使其工作:
类客户端自动完成选择(自动完成选择):
def get_url(自身):
模型=客户端
返回反向(self.url\u name%(self.admin\u site.name,model.\u meta.app\u label,model.\u meta.model\u name))
类ClientChoiceField(forms.ModelChoiceField):
定义初始化(self,queryset=None,widget=None,**kwargs):
如果queryset为无:
queryset=Client.objects.all()
如果小部件为无:
widget=ClientAutocompleteSelect(无,admin.site)#将'None'传递给'rel'`
super()
定义到python(自身,值):
返回值#只返回客户端id,而不是客户端对象
类MyAdminForm(forms.ModelForm):
client_id=ClientChoiceField()
...
这要求最终用户具有对所查询模型的自动完成端点的管理员读取权限。不过,您可以进行更多的黑客攻击来更改
获取url
,并使用您自己的端点提供搜索结果。我花了几个小时试图理解为什么我的代码(基于@Tim的答案构建)无法工作,直到我偶然发现一条关于缺少css/js文件引用的评论
以下是一个完整的工作解决方案,可以在任何自定义表单中使用AutocompleteSelect小部件,供同时具有给定模型“staff”和“view”访问权限的登录用户使用:
from django.urls import reverse
from django.contrib.admin.widgets import AutocompleteSelect
from django.contrib import admin
class UserAutocompleteSelect(AutocompleteSelect):
def get_url(self):
model = CustomUser
return reverse(self.url_name % (self.admin_site.name, model._meta.app_label, model._meta.model_name))
class UserChoiceField(forms.ModelChoiceField):
def __init__(self, queryset=None, widget=None, **kwargs):
if queryset is None:
queryset = CustomUser.objects.all()
if widget is None:
widget = UserAutocompleteSelect(None, admin.site) # pass `None` for `rel`
super().__init__(queryset, widget=widget, **kwargs)
class UserAutocompleteSelectForm(forms.ModelForm):
"""
for changing user on Play objects
using amdin module autocomplete
"""
user = UserChoiceField(
# queryset=CustomUser.objects.all(),
help_text=_('Select the user to replace the current one')
)
class Meta:
model = Play
fields = ('user', )
您可以使用相同的功能,用自己的型号替换CustomUser
和Play
如果(像我一样)这与您正在使用的html模板不兼容,这意味着您需要将所需的css/js文件包含到模板中。下面是一个简单的方法:
如果该表格在视图中声明为:
form = UserAutocompleteSelectForm()
...
context = {
'form': form,
...
}
return render(request, 'users/change_user.html', context)
您应该向html模板添加以下行,以包含所需的css/js文件:
{% block extrahead %}
{{ block.super }}
{{ form.media }}
{% endblock %}
在ModelAdmin中,您只需添加
autocomplete\u fields=('your\u field',)
No我正在尝试在ModelAdmin之外执行此操作。我正试着用我自己的方式去做form@Cybershoe您能找到解决方案吗?小部件依赖于能够查询需要管理员访问的“自动完成”端点,因此,如果该人员已登录并且对给定模型具有“人员”和“查看”访问权限,则它只能在管理员之外工作。Invoice.incident.field.remote\u字段
一直使用到Django 3.2中的Django 3.1,它只是Invoice.incident.field
{% block extrahead %}
{{ block.super }}
{{ form.media }}
{% endblock %}