Django - настраиваемые атрибуты для полей модели - PullRequest
1 голос
/ 07 декабря 2011

Есть ли способ в Django добавить пользовательские атрибуты в поля модели (не прибегая к полям подклассов)?

Я хотел бы отображать только определенные поля в определенных разделах моего шаблона.Это потому, что в конечном итоге каждый тип поля будет отображаться на отдельной вкладке.Я думал о добавлении специального атрибута в каждое поле, чтобы определить, в какой раздел / вкладку он должен войти. Но пока мне не повезло.

У меня есть несколько типов полей:

class Enum(set):
    def __getattr__(self, name):
        if name in self:
            return name
        raise AttributeError

FieldTypes = Enum(["one","two","three",])

И несколько моделей:

class Model1(models.Model):
  a = models.CharField()
  b = models.ForeignKey('Model2')
  c = models.IntegerField()
  a.type = FieldTypes.one  # this obviously doesn't work
  b.type = FieldTypes.two  # this obviously doesn't work
  c.type = FieldTypes.three  # this obviously doesn't work

class Model2(models.Model):
  d = models.CharField()

И форма:

class Form1(forms.ModelForm):
  class Meta:
    model = Mode1

И шаблон:

{% for fieldType in FieldTypes %}
  <div class="{{fieldType}}">
      {% for field in form %}
        {% if field.type = fieldType %}
          {{ field }}
         {% endif %}
      {% endfor %} 
  </div>
{% endfor %}

Но это не такработа.

Идеи?Или другие предложения по размещению только определенных полей в определенных разделах страницы?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 07 декабря 2011

В общем, я бы оставил эту логику вне модельного класса. Модели не должны быть запутаны с элементами презентации, если вы можете помочь, и выбор полей для отображения в форме кажется проблемой презентации. К счастью, класс Form обеспечивает хороший, ориентированный на пользовательский интерфейс уровень между уровнем данных (модель) и уровнем представления (представление и шаблон).

Вот как я обращался к этому в прошлом. В своем классе Form я создал список групп полей, каждая из которых имеет заголовок и список имен полей, которые они содержат:

class MyModelForm(forms.ModelForm):
    field_groups = (
        {'name':'Group One', 'fields':('a', 'b', 'c')},
        {'name':'Group Two', 'fields':('d', 'e')},
    )
    class Meta:
        model = MyModel

Затем в шаблоне я прошел по группам, и в этот цикл были включены условные поля:

{% for group in form.field_groups %}
<h3 class="groupheader">{{group.name}}</h3>
    {% for field in form %}
        {% if field.name in group.fields %}
        <div class="fieldWrapper">
            {{ field.errors }}
            {{ field.label_tag }}: {{ field }}
        </div>
        {% endif %}
    {% endfor %}
{% endfor %}

Это позволяет вам управлять группировкой и отображением полей формы в классе MyModelForm, который является разумным местом для логики представления.

0 голосов
/ 11 декабря 2011

Оказывается, я хочу эту логику в своем классе моделей; типы полей используются не только для определения, где и как их отображать (хотя и для этого они используются). Я пришел к следующему решению.

Я определил несколько классов для хранения набора типов полей:

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 %}
0 голосов
/ 07 декабря 2011

Это возможно!

class Model1(models.Model):
   a = models.CharField()
   b = models.ForeignKey('Model2')
   c = models.IntegerField()

И форма:

class Form1(forms.ModelForm):

  def __init__(self, *args, **kwargs):
    super(Form1, self).__init__(*args, **kwargs)
    self.fields['a'].type = FieldTypes.one  # this obviously doesn't work
    self.fields['b'].type = FieldTypes.two  # this obviously doesn't work
    self.fields['c'].type = FieldTypes.three  # this obviously doesn't work


  class Meta:
    model = Mode1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...