2009-02-03 4 views
4

Как использовать логические варианты в поле модели, чтобы включить/отключить другие поля. Если логическое значение true/false, я хочу, чтобы он включал/отключал другие поля модели. Есть ли способ изначально выразить эти отношения с помощью моделей/форм/виджетов django? Я продолжаю писать пользовательские шаблоны для моделирования этих отношений, но не могу найти хороший способ представить их в django без специального шаблона.Как использовать формы/модели django для представления выбора между полями?

Например:

 
class PointInTime(models.Model): 
    is_absolute_time = models.BooleanField() 
    absolute_time = models.DateTimeField() 
    is_relative_time = models.BooleanField() 
    days_before = models.IntegerField() 

Так что, если is_absolute_time это правда, я хочу, чтобы запись absolute_time быть доступны для редактирования в графическом интерфейсе и записи days_before быть неактивны и не редактируется. Если флаг «is_relative_time» имеет значение «Истина», я хочу, чтобы абзац абсолютного значения был выделен серым цветом, а значение days_before для редактирования. Таким образом is_absolute_time и is_relative_time будут переключателями в той же Группе в графическом интерфейсе, и их два соответствующих поля будут доступны только при выборе переключателя. Это легко сделать в настраиваемом шаблоне, но есть ли способ использовать модель/форму в django, чтобы изначально показать это отношение?

ответ

6

Было бы полезно прояснить, что вы подразумеваете под «изначально показать эти отношения», и четко продумать разделение проблем.

Если все, что вы хотите, должно «седеть» или отключить определенное поле, основанное на значении другого поля, это просто проблема с представлением/UI, поэтому шаблон (и/или Javascript) является подходящим местом для справиться.

Если вы хотите подтвердить, что представленные данные являются внутренне согласованными (то есть, абсолютное_пополнение заполняется, если is_absolute_time равно True и т. Д.), Это проблема проверки формы. Место для этой логики - в методе clean() объекта Form или ModelForm.

Если вы хотите, чтобы модель PointInTime не могла быть сохранена в базе данных без внутренней согласованности, это проблема уровня данных. Место для этого - в пользовательском методе save() на вашем объекте модели (Django 1.2 будет включать more extensive model validation system).

Все эти опции включают в себя обязательный код для ввода необходимых вам данных с этими конкретными полями. Возможно, вы ищете способ представить декларативную ситуацию в своей модели, чтобы код во всех трех случаях можно писать в общих чертах, а не специально.Там нет встроенных в Django способ сделать это, но вы могли бы, конечно, сделать что-то вроде:

class PointInTime(models.Model): 
    field_dependencies = {'is_absolute_time': 'absolute_time', 
          'is_relative_time': 'days_before'} 
    ... fields here ... 

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

Наконец, несколько дизайна схем альтернативы вы можете рассмотреть, чтобы получить слой данных лучше нормирован:

  • Если есть только два действительные состояния (абсолютные и относительные), используйте одно булево поле вместо из двух. Затем вы избегаете возможных несоответствий (что означает, что оба логических значения являются ложными или истинными?)

  • или упростить дальнейшее устранение булевых объектов полностью и просто используя значения Null в одном или другом абсолютном_time/days_before.

  • Если существует более двух допустимых состояний, используйте один IntegerField или CharField с вариантами вместо использования двух булевых полей. По той же причине, что и выше, но может содержать более двух вариантов.

  • Поскольку RelativeTime и AbsoluteTime, похоже, не разделяют какие-либо поля данных друг с другом, рассмотрите их разделение на отдельные модели полностью. Если у вас есть другие модели, для которых требуется ForeignKey, то вы можете моделировать это с наследованием (оба RelativeTime и AbsoluteTime наследуются от PointInTime, другие модели имеют ForeignKeys для PointInTime).

1

Я не совсем уверен, что вы делаете с этими объектами, но в зависимости от того, какой пользователь выбирает, вы указываете на один момент времени. «5 дней назад» - «четверг» и наоборот.

Так что, если даты не катятся с сайтом (например, запись с «5 днями назад» по-прежнему будет означать четверг, завтра и т. Д.), Неужели это только проблема интерфейса? Если это так, я придерживаюсь единственного значения для даты в вашей модели и позволяю форме и виду выполнять всю работу.

Это решает автоматическую сгенерированную административную сторону вещей, поскольку у вас будет только одно поле, в котором вы будете бороться, но это не даст вам выбора между ними, если вы не напишете свой собственный виджет формы и не переопределите класс ModelAdmin для вашей модели.

Если это не так, пожалуйста, проигнорируйте этот ответ.

+0

Относительное время будет катиться по отношению к некоторому другому значению даты и времени (либо сегодня, либо в какой-либо другой записи.) Таким образом, он по-разному моделируется в базе данных, я бы фактически сохранил «5» в качестве целого числа для представления относительное время истекло за 5 дней до некоторого другого времени. – MikeN