Оказывается, я хочу эту логику в своем классе моделей; типы полей используются не только для определения, где и как их отображать (хотя и для этого они используются). Я пришел к следующему решению.
Я определил несколько классов для хранения набора типов полей:
class FieldType(object):
def __init__(self, type=None, name=None):
self._type = type
self._name = name
def getType(self):
return self._type
def getName(self):
return self._name
class FieldTypeList(deque):
def __getattr__(self,type):
for ft in self:
if ft.getType() == type:
return ft
raise AttributeError
FieldTypes = FieldTypeList([FieldType("ONE","The Name Of Field One"),FieldType("TWO","The Name Of Field Two")])
И несколько моделей, каждая из которых имеет набор сопоставлений типов полей с определенными именами полей (в этом примере поля 'a', 'b' и 'c' имеют тип 'ONE' и поле 'd 'типа' ДВА '):
class ParentModel(models.Model):
_fieldsByType = {}
a = models.CharField()
b = models.CharField()
def __init__(self, *args, **kwargs):
super(ParentModel, self).__init__(*args, **kwargs)
for ft in FieldTypes:
self.setFieldsOfType(ft, [])
self.setFieldsOfType(FieldTypes.ONE, ['a','b'])
def setFieldsOfType(self,type,fields):
typeKey = type.getType()
if typeKey in self._fieldsByType:
self._fieldsByType[typeKey] += fields
else:
self._fieldsByType[typeKey] = fields
class ChildModel(ParentModel):
_fieldsByType = {} # not really sure why I have to repeat this attribute in the derived class
c = models.CharField()
d = models.CharField()
def __init__(self, *args, **kwargs):
super(ChildModel, self).__init__(*args, **kwargs)
self.setFieldsOfType(FieldTypes. ['c'])
self.setFieldsOfType(FieldTypes. ['d'])
У меня есть базовая форма:
class MyForm(forms.ModelForm):
class Meta:
model = ChildModel
И пользовательский фильтр для возврата всех полей данного типа из определенной формы (обратите внимание, доступ к модели из формы через ее мета-класс):
@register.filter
def getFieldsOfType(form,type):
return form.Meta.model._fieldsByType[type.getType()]
И, наконец, шаблон, чтобы собрать все вместе (шаблон принимает MyForm и FieldTypes):
{% for type in types %}
<div id="{{type.getType}}">
{% with fieldsOfType=form|getFieldsOfType:type %}
{% for field in form %}
{% if field.name in fieldsOfType %}
<p>
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
</p>
{% endif %}
{% endfor %}
{% endwith %}
</div>
{% endfor %}