如何指定Django表单中字段的顺序?

2024-09-27 19:21:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我们正在使用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(...),但是如何定义来自模型的字段呢?我只想在字段列表的开头添加两个附加字段


Tags: todjangoself表单fieldfieldsgetloc
3条回答

OrderedDict来自标准库

from collections import OrderedDict

实例有.move_to_end(),它只是说你dict对象没有.move_to_end(),这意味着你正在使用一个普通的dict。将它转换成这样一个OrderedDict

x = { "key" : "value"}
y = OrderedDict(x)
# OrderedDict([('key', 'value')])

现在.move_to_end()将起作用

Is there a change in the implementation of the fields in forms

Django 2.2和3之间的变化是声明字段的初始化方式:

我想这是因为Django3支持版本3.6或更高版本(https://docs.djangoproject.com/en/3.0/faq/install/)的Python,并且Python3.6 dict是按插入顺序(Are dictionaries ordered in Python 3.6+?)的


我会将self.fields转换为OrderedDict(基本上回到2.2版中的情况),以再次启用self.fields.move_to_end

from collections import OrderedDict


class LocalizedFirstLastNameMixin(object):
    def __init__(self, *args, **kwargs):
        self.language_code = kwargs.pop('language_code', 'en')
        super().__init__(*args, **kwargs)
        self.fields = OrderedDict(self.fields)
        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, '')

我在Django developers mailing list中询问过,我被告知自己不要操纵字段的顺序,而是使用here中记录的受支持的API方法。因此,我更改了代码并使用了self.order_fields

class LocalizedFirstLastNameMixin(object):
    def __init__(self, *args, **kwargs):
        self.language_code = kwargs.pop('language_code', 'en')
        super().__init__(*args, **kwargs)
        localized_fields = self.get_localized_fields()
        for loc_field in localized_fields:
            self.fields[loc_field] = User._meta.get_field(loc_field).formfield()
            self.fields[loc_field].required = True
            self.initial[loc_field] = getattr(self.instance, loc_field, '')
        self.order_fields(field_order=localized_fields)

请注意,我只对前两个字段进行排序。所有其他字段都保持默认顺序。我现在也不必按相反的顺序添加字段

相关问题 更多 >

    热门问题