Началось всё с того что надо было часто создавать однотипные формы и сохранять введённые данные в базу. По суте форма всегда одна и та же — «Заявка на регистрацию» — но в зависимости от мероприятия поля в ней разные.
Обязанности подготовки формы надо было переложить на администратора сайта, поэтому было принято решение создать механизм управления формами через админский интерфейс Django. Так появилось приложение CDBForms.
Идея очень простая — создать модели для описания форм и хранения введённых данных. Соответственно появились модели Template (шалон формы), TemplateField (поле в шаблоне формы) и FieldParameter (параметры поля) для хранения информации о формах (шаблоны форм) и модели Record и RecordData для хранения данных, введённых через формы.
Собственно:
Дальше осталось только реализовать класс нашей формы:
Форма готова к использованию, осталось только реализовать удобный интерфейс администратора. Пример как это работает можно посмотреть тут и тут.
Скачать код можно с code.google.com/p/django-cdbforms
Кстати, если кому-то интересно, то буду рад сотрудничеству! Спасибо!
Обязанности подготовки формы надо было переложить на администратора сайта, поэтому было принято решение создать механизм управления формами через админский интерфейс Django. Так появилось приложение CDBForms.
Идея очень простая — создать модели для описания форм и хранения введённых данных. Соответственно появились модели Template (шалон формы), TemplateField (поле в шаблоне формы) и FieldParameter (параметры поля) для хранения информации о формах (шаблоны форм) и модели Record и RecordData для хранения данных, введённых через формы.
Собственно:
class Template(models.Model): tag = models.SlugField(max_length=16, unique=True) title = models.CharField(max_length=50) def fields(self): return TemplateField.objects.filter(template=self).order_by('tab') def __unicode__(self): return self.title class TemplateField(models.Model): FieldTypes = (('T', 'Text'), ('B', 'Bool'), ('E', 'E-mail'), ('U', 'URL'), ('C', 'Choices'),) template = models.ForeignKey(Template) tag = models.SlugField(max_length=32) title = models.CharField(max_length=50) type = models.CharField(max_length=1, choices=FieldTypes) tab = models.IntegerField(default=0) required = models.BooleanField(default=True) def __unicode__(self): return u'%s: %s' % (self.template, self.tag) def parameters(self): return FieldParameter.objects.filter(field=self).order_by('tab') class Meta: unique_together = ("template", "tag") class FieldParameter(models.Model): field = models.ForeignKey(TemplateField) tag = models.SlugField(max_length=32) value = models.CharField(max_length=255) tab = models.IntegerField(default=0) def __unicode__(self): return u'%s: %s = %s' % (self.field, self.tag, self.value) class Meta: unique_together = ("field", "tag", "value") class Record(models.Model): template = models.ForeignKey(Template) dt = models.DateTimeField() def __unicode__(self): return u'%s @ %s' % (self.template, self.dt) class RecordData(models.Model): record = models.ForeignKey(Record) field = models.ForeignKey(TemplateField) value = models.CharField(max_length=255) def __unicode__(self): return u'%s %s' % (self.record, self.field) class Meta: unique_together = ("record", "field")
Дальше осталось только реализовать класс нашей формы:
class CDBForm(forms.Form): def __init__(self, template=None, tag=None, *args, **kwargs): if template: self.template = template elif tag: self.template = Template.objects.get(tag=tag) fields = self.template.fields() for field in fields: if field.type == "B": self.base_fields[field.tag] = forms.BooleanField(label=field.title, required=field.required) elif field.type == "T": self.base_fields[field.tag] = forms.CharField(label=field.title, required=field.required) elif field.type == "C": choices = [] for parameter in field.parameters(): if parameter.tag == "choice": choices.append((parameter.value, parameter.value)) self.base_fields[field.tag] = forms.ChoiceField(choices=choices, label=field.title, required=field.required) elif field.type == "E": self.base_fields[field.tag] = forms.EmailField(label=field.title, required=field.required) elif field.type == "U": self.base_fields[field.tag] = forms.URLField(label=field.title, required=field.required) forms.Form.__init__(self, *args, **kwargs) def save(self, commit=True): data = self.cleaned_data if commit: rec = Record(template=self.template, dt=datetime.now()) rec.save() for k,v in data.iteritems(): f = TemplateField.objects.get(template=self.template, tag=k) d = RecordData(record=rec, field=f, value=v) d.save() return data
Форма готова к использованию, осталось только реализовать удобный интерфейс администратора. Пример как это работает можно посмотреть тут и тут.
Скачать код можно с code.google.com/p/django-cdbforms
Кстати, если кому-то интересно, то буду рад сотрудничеству! Спасибо!