我们正在使用Django 2.2,我想升级到Django 3.0。我们有一个mixin(写于2017年),它可以向表单添加字段:
class LocalizedFirstLastNameMixin(object):
def __init__(self, *args, **kwargs):
self.language_code = kwargs.pop('language_code', 'en')
super().__init__(*args, **kwargs)
for loc_field in reversed(self.get_localized_fields()):
self.fields[loc_field] = User._meta.get_field(loc_field).formfield()
self.fields[loc_field].required = True
self.fields.move_to_end(loc_field, last=False)
self.initial[loc_field] = getattr(self.instance, loc_field, '')
self.get_localized_fields()
返回英语的('first_name_en', 'last_name_en')
(按此顺序),或本地化为我们正在使用的当前语言的相同内容。
这个mixin被用作继承自ModelForm
的表单的基类之一:
class RegistrationForm(AddAttributesToFieldsMixin, CleanEmailMixin, CleanNewPasswordMixin, CleanDateOfBirthMixin, LocalizedFirstLastNameMixin, forms.ModelForm):
....
class ProfileForm(AddAttributesToFieldsMixin, CleanDateOfBirthMixin, LocalizedFirstLastNameMixin, forms.ModelForm):
....
它适用于Django 2.2版本。但是当我升级到3.0时,我得到这个错误消息:AttributeError: 'dict' object has no attribute 'move_to_end'
此函数的信息:Move an existing element to the end (or beginning if last==False).
它属于OrderedDict
。
所以我想我们希望这些字段在表单字段的开头。
Django 3.0中表单中字段的实现有变化吗?如何指定字段的顺序?如果我改变它,它会在以前的版本中工作吗,比如Django 2.2?
我检查了Django 3.0 release notes以及从3.0.1到3.0.5的版本,我没有找到任何关于这个问题的文档。
**更新:**我发现我可以调用self.order_fields(...)
,但如何定义来自模型的字段?我只想在字段列表的开头添加两个额外的字段。
4条答案
按热度按时间koaltpgm1#
我在Django开发者邮件列表中询问,他们告诉我不要自己操作字段的顺序,而是使用这里记录的支持的API方法。所以我修改了代码,使用了
self.order_fields
:请注意,我只对前两个字段进行排序。所有其他字段都按默认顺序保留。我现在也不必以相反的顺序添加字段。
lymnna712#
表单中字段的实现是否有变化
Django 2.2和3之间的变化是声明字段的初始化方式:
我猜这是因为Django 3支持Python 3.6或更高版本(https://docs.djangoproject.com/en/3.0/faq/install/),并且Python 3.6的dicts是插入顺序的(Are dictionaries ordered in Python 3.6+?)。
我会将
self.fields
转换为OrderedDict
(基本上回到2.2版中的状态),以再次启用self.fields.move_to_end
。pbwdgjma3#
OrderedDict
来自标准库。示例有
.move_to_end()
,它只是说你的dict
对象没有.move_to_end()
,这意味着你使用的是一个普通的dict。转换为OrderedDict
,如下所示现在
.move_to_end()
将工作jaxagkaj4#
我来晚了,但这可能对别人有用。在最近的Python(3.6+)中,普通的
dict
按照键的添加顺序保存键。对于早期版本,您需要使用collections.OrderedDict
。Django曾经使用它自己的类似dict的类,但现在使用vanilladict
。print( type(form_instance.fields))
如果有疑问。无论如何,您可以通过在表单的
__init__
方法中重新定义self.fields
来以任何方式重新排序字段。如:由于我已经编写了一个非常通用的reorder_dict函数,所以它在这里