最新版本的 Django autocomplete light 中 modelform_factory 的替代品是什么?
What is the replacement for modelform_factory in the newest version of Django autocomplete light?
在以前版本的 autocomplete light 中,有一种添加新表单的非常快捷的方法。
form = modelform_factory(ModelName, fields='__all__')
如果模型注册了一个自动完成视图,这将根据给定的模型自动构建一个新表单。非常快速和容易。在今天发布的最新版本 3.1.6 中,此功能似乎已被删除。我不得不回去重新做所有的事情来让我们升级,我想知道在我刚刚错过的新版本中是否有类似旧 modelform_factory
的东西可用。或者是否有一种快速的方法来设置可以轻松重用的通用自动完成视图/表单?任何想法表示赞赏。
所以经过大量搜索,我无法找到任何类似于以前的 modelform_factory 自动完成灯的东西,所以我决定自己制作。以下是直接取自我们生产 CMS 中的示例。
from dal import autocomplete
from mymodels import ThisModel, ThatModel, AnotherModel
def autocomplete_form_factory(ac_model, *args, **kwargs):
field_url_dict = {}
m2m = ('mypeeps', 'yourpeeps',)
if ac_model in (ThisModel, ThatModel):
# Connects the "stuff_field" of these
# models to the url named "stuff-autocomplete"
field_url_dict = {
'stuff_field': 'stuff'
}
elif ac_model == AnotherModel:
# Connects AnotherModel's ForeignKey field "headhoncho"
# and its ManyToManyFields "mypeeps" and "yourpeeps"
# to the "peeps-autocomplete" url
field_url_dict = {
'headhoncho': 'peeps',
'mypeeps': 'peeps',
'yourpeeps': 'peeps',
}
# Assign the appropriate widgets based on this model's autocomplete dictionary
ac_widgets = {}
ac_fields = kwargs.get('fields', ('__all__'))
for field, url in field_url_dict.iteritems():
is_m2m = field in m2m
text = 'Type to return a list of %s...' if is_m2m else 'Type to return a %s list...'
kwargs = {
'url': '%s-autocomplete' % url,
'attrs': {
'data-placeholder': text % ac_model._meta.get_field(field).verbose_name,
'data-minimum-input-length': 3,
}
}
ac_widgets[field] = autocomplete.ModelSelect2Multiple(**kwargs) if is_m2m else autocomplete.ModelSelect2(**kwargs)
# Create the form
class DynamicAutocompleteForm(forms.ModelForm):
class Meta:
model = ac_model
fields = ac_fields
widgets = ac_widgets
return DynamicAutocompleteForm
对于相应的视图,您可以按照以下方式进行操作:
class BaseAutocomplete(autocomplete.Select2QuerySetView):
model = None
fields = ['title']
filters = {}
def get_queryset(self):
if not self.request.user.is_authenticated() or not self.q or len(self.q) < 3:
return self.model.objects.none()
# OR all of our field searches together
obj = Q()
for field in self.fields:
kwargs = {}
kwargs['%s__icontains' % field] = self.q
obj = obj | Q(**kwargs)
return self.model.objects.filter(obj).filter(**self.filters)
class StuffAutocomplete(BaseAutocomplete):
model = Stuff
filters = {'is_awesome': True}
class PeepsAutocomplete(BaseAutocomplete):
model = Peeps
fields = ['name', 'notes']
对于 url,您可以使用以下内容:
url(r'^stuff-autocomplete/$', StuffAutocomplete.as_view(), name='stuff-autocomplete'),
url(r'^peeps-autocomplete/$', PeepsAutocomplete.as_view(), name='peeps-autocomplete',),
要在您的代码中使用表单工厂,您可以使用如下内容,将结果分配给模型管理员的表单或将其用作更复杂表单的基础:
autocomplete_form_factory(ThisModel)
autocomplete_form_factory(AnotherModel, fields=["headhoncho", "mypeeps"])
这模仿了我们早期使用自动完成功能 modelform_factory 的功能,这使得创建自动完成表单并在设置完所有内容后根据需要将它们添加到管理中变得非常简单。希望这会帮助一些人节省一些时间。
在以前版本的 autocomplete light 中,有一种添加新表单的非常快捷的方法。
form = modelform_factory(ModelName, fields='__all__')
如果模型注册了一个自动完成视图,这将根据给定的模型自动构建一个新表单。非常快速和容易。在今天发布的最新版本 3.1.6 中,此功能似乎已被删除。我不得不回去重新做所有的事情来让我们升级,我想知道在我刚刚错过的新版本中是否有类似旧 modelform_factory
的东西可用。或者是否有一种快速的方法来设置可以轻松重用的通用自动完成视图/表单?任何想法表示赞赏。
所以经过大量搜索,我无法找到任何类似于以前的 modelform_factory 自动完成灯的东西,所以我决定自己制作。以下是直接取自我们生产 CMS 中的示例。
from dal import autocomplete
from mymodels import ThisModel, ThatModel, AnotherModel
def autocomplete_form_factory(ac_model, *args, **kwargs):
field_url_dict = {}
m2m = ('mypeeps', 'yourpeeps',)
if ac_model in (ThisModel, ThatModel):
# Connects the "stuff_field" of these
# models to the url named "stuff-autocomplete"
field_url_dict = {
'stuff_field': 'stuff'
}
elif ac_model == AnotherModel:
# Connects AnotherModel's ForeignKey field "headhoncho"
# and its ManyToManyFields "mypeeps" and "yourpeeps"
# to the "peeps-autocomplete" url
field_url_dict = {
'headhoncho': 'peeps',
'mypeeps': 'peeps',
'yourpeeps': 'peeps',
}
# Assign the appropriate widgets based on this model's autocomplete dictionary
ac_widgets = {}
ac_fields = kwargs.get('fields', ('__all__'))
for field, url in field_url_dict.iteritems():
is_m2m = field in m2m
text = 'Type to return a list of %s...' if is_m2m else 'Type to return a %s list...'
kwargs = {
'url': '%s-autocomplete' % url,
'attrs': {
'data-placeholder': text % ac_model._meta.get_field(field).verbose_name,
'data-minimum-input-length': 3,
}
}
ac_widgets[field] = autocomplete.ModelSelect2Multiple(**kwargs) if is_m2m else autocomplete.ModelSelect2(**kwargs)
# Create the form
class DynamicAutocompleteForm(forms.ModelForm):
class Meta:
model = ac_model
fields = ac_fields
widgets = ac_widgets
return DynamicAutocompleteForm
对于相应的视图,您可以按照以下方式进行操作:
class BaseAutocomplete(autocomplete.Select2QuerySetView):
model = None
fields = ['title']
filters = {}
def get_queryset(self):
if not self.request.user.is_authenticated() or not self.q or len(self.q) < 3:
return self.model.objects.none()
# OR all of our field searches together
obj = Q()
for field in self.fields:
kwargs = {}
kwargs['%s__icontains' % field] = self.q
obj = obj | Q(**kwargs)
return self.model.objects.filter(obj).filter(**self.filters)
class StuffAutocomplete(BaseAutocomplete):
model = Stuff
filters = {'is_awesome': True}
class PeepsAutocomplete(BaseAutocomplete):
model = Peeps
fields = ['name', 'notes']
对于 url,您可以使用以下内容:
url(r'^stuff-autocomplete/$', StuffAutocomplete.as_view(), name='stuff-autocomplete'),
url(r'^peeps-autocomplete/$', PeepsAutocomplete.as_view(), name='peeps-autocomplete',),
要在您的代码中使用表单工厂,您可以使用如下内容,将结果分配给模型管理员的表单或将其用作更复杂表单的基础:
autocomplete_form_factory(ThisModel)
autocomplete_form_factory(AnotherModel, fields=["headhoncho", "mypeeps"])
这模仿了我们早期使用自动完成功能 modelform_factory 的功能,这使得创建自动完成表单并在设置完所有内容后根据需要将它们添加到管理中变得非常简单。希望这会帮助一些人节省一些时间。