Django：フォームのField順序は定義順が保持される？

#Django：フォームのField順序は定義順が保持される？
Djangoのフォームからフィールド定義を取得しようとして気になった。
**fields**プロパティでとれるやつ。
これって**OrderedDict**のオブジェクトだけどそのOrder（順番）って信じていいの？

##公式ドキュメントを見る
ここ（[Notes on field ordering](https://docs.djangoproject.com/ja/2.1/ref/forms/api/#notes-on-field-ordering)）とかみるとFormで定義した順番でフィールドの表示も決まる。また、

>By default Form.field_order=None, which retains the order in which you define the fields in your form class.

なんていう記述を見ると**fields**の順番も**field_order**で変更しない限り**Form**クラスの定義順を保持するように見える。

##Djangoのソースを見る
なんとなく疑り深いだけの気もするのだけれどもうちょっと確証じみたものがほしい。
ってんでforms.pyのソースコード見ると、

```python:forms.py

@html_safe
class BaseForm:
    """
    The main implementation of all the Form logic. Note that this class is
    different than Form. See the comments by the Form class for more info. Any
    improvements to the form API should be made to this class, not to the Form
    class.
    """
    default_renderer = None
    field_order = None
    prefix = None
    use_required_attribute = True

    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
                 initial=None, error_class=ErrorList, label_suffix=None,
                 empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None):
        self.is_bound = data is not None or files is not None
        self.data = {} if data is None else data
        self.files = {} if files is None else files
        self.auto_id = auto_id
        if prefix is not None:
            self.prefix = prefix
        self.initial = initial or {}
        self.error_class = error_class
        # Translators: This is the default suffix added to form field labels
        self.label_suffix = label_suffix if label_suffix is not None else _(':')
        self.empty_permitted = empty_permitted
        self._errors = None  # Stores the errors after clean() has been called.

        # The base_fields class attribute is the *class-wide* definition of
        # fields. Because a particular *instance* of the class might want to
        # alter self.fields, we create self.fields here by copying base_fields.
        # Instances should always modify self.fields; they should not modify
        # self.base_fields.
        self.fields = copy.deepcopy(self.base_fields)

```

ん、ここで**fields**のインスタンスができてる。
*deepcopy*している**base_fields**を追ってくと、

```python:forms.py

class DeclarativeFieldsMetaclass(MediaDefiningClass):
    """Collect Fields declared on the base classes."""
    def __new__(mcs, name, bases, attrs):
        # Collect fields from current class.
        current_fields = []
        for key, value in list(attrs.items()):
            if isinstance(value, Field):
                current_fields.append((key, value))
                attrs.pop(key)
        attrs['declared_fields'] = OrderedDict(current_fields)

        new_class = super(DeclarativeFieldsMetaclass, mcs).__new__(mcs, name, bases, attrs)

        # Walk through the MRO.
        declared_fields = OrderedDict()
        for base in reversed(new_class.__mro__):
            # Collect fields from base class.
            if hasattr(base, 'declared_fields'):
                declared_fields.update(base.declared_fields)

            # Field shadowing.
            for attr, value in base.__dict__.items():
                if value is None and attr in declared_fields:
                    declared_fields.pop(attr)

        new_class.base_fields = declared_fields
        new_class.declared_fields = declared_fields

        return new_class

    @classmethod
    def __prepare__(metacls, name, bases, **kwds):
        # Remember the order in which form fields are defined.
        return OrderedDict()
```

途中わかりずらいが、**DeclarativeFieldsMetaclass**という**type**を継承したメタクラスの*\_\_new\_\_*メソッドで、引数の**attrs**から**Field**だけ抜き出して**OrderedDict**にセットしているように見える。

## PEP520をチラ見する

でも、じゃあこの**attrs**の順番ってどうなるのって振り出しに戻るかに思われたところで、以下のやり取りをCode Examplesを見つけました。
[[metaclass] 宣言したのと同じ順序でクラス属性を読み込む方法は？](https://code-examples.net/ja/q/440c0b)

回答によると、現在のPython（ver3.6~）ではクラスにおける定義順序は保持されているのだとのこと。。え？そうなの？
3.5より前ではメタクラスの*\_\_prepare\_\_*メソッドで*collections.OrderedDict()*を返せばよい。

この*\_\_prepare\_\_*とは何か？
[PEP520](https://www.python.org/dev/peps/pep-0520/)より抜粋。
>The class attribute definition order is represented by the insertion order of names in the definition namespace. Thus, we can have access to the definition order by switching the definition namespace to an ordered mapping, such as collections.OrderedDict. This is feasible using a metaclass and \_\_prepare\_\_, as described above. In fact, exactly this is by far the most common use case for using \_\_prepare\_\_.

「クラス属性定義の順序は定義名前空間における名前の挿入順によってあらわされる。そういう訳で、われわれは定義順序に対して、例えば**OrderdDict**のような順序づけられたマッピングに定義空間を切り替えることによってアクセスできるようになる。このことは、上述のように*metaclass*と*\_\_prepare\_\_*の使用によって可能となる。実際、これが*\_\_prepare\_\_*を使用する一番のユースケースなのである。」

なるほど。

##結論
フォームのField順序は定義順が保持される？
**――されてます。**