models.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. from __future__ import unicode_literals
  2. from django.db import models
  3. from django.utils.encoding import python_2_unicode_compatible
  4. from django.utils.translation import ugettext_lazy as _
  5. from mezzanine.conf import settings
  6. from mezzanine.core.fields import RichTextField
  7. from mezzanine.core.models import Orderable, RichText
  8. from mezzanine.forms import fields
  9. from mezzanine.pages.models import Page
  10. class Form(Page, RichText):
  11. """
  12. A user-built form.
  13. """
  14. button_text = models.CharField(_("Button text"), max_length=50, blank=True)
  15. response = RichTextField(_("Response"))
  16. send_email = models.BooleanField(_("Send email to user"), default=True,
  17. help_text=_("To send an email to the email address supplied in "
  18. "the form upon submission, check this box."))
  19. email_from = models.EmailField(_("From address"), max_length=254,
  20. help_text=_("The address the email will be sent from"), blank=True)
  21. email_copies = models.CharField(_("Send email to others"), blank=True,
  22. help_text=_("Provide a comma separated list of email addresses "
  23. "to be notified upon form submission. Leave blank to "
  24. "disable notifications."),
  25. max_length=200)
  26. email_subject = models.CharField(_("Subject"), max_length=200, blank=True)
  27. email_message = models.TextField(_("Message"), blank=True,
  28. help_text=_("Emails sent based on the above options will contain "
  29. "each of the form fields entered. You can also enter "
  30. "a message here that will be included in the email."))
  31. class Meta:
  32. verbose_name = _("Form")
  33. verbose_name_plural = _("Forms")
  34. class FieldManager(models.Manager):
  35. """
  36. Only show visible fields when displaying actual form..
  37. """
  38. def visible(self):
  39. return self.filter(visible=True)
  40. @python_2_unicode_compatible
  41. class AbstractBaseField(Orderable):
  42. """
  43. A field for a user-built form.
  44. """
  45. label = models.CharField(_("Label"),
  46. max_length=settings.FORMS_LABEL_MAX_LENGTH)
  47. field_type = models.IntegerField(_("Type"), choices=fields.NAMES)
  48. required = models.BooleanField(_("Required"), default=True)
  49. visible = models.BooleanField(_("Visible"), default=True)
  50. choices = models.CharField(_("Choices"), max_length=1000, blank=True,
  51. help_text=_("Comma separated options where applicable. If an option "
  52. "itself contains commas, surround the option with `backticks`."))
  53. default = models.CharField(_("Default value"), blank=True,
  54. max_length=settings.FORMS_FIELD_MAX_LENGTH)
  55. placeholder_text = models.CharField(_("Placeholder Text"), blank=True,
  56. max_length=100)
  57. help_text = models.CharField(_("Help text"), blank=True, max_length=100)
  58. objects = FieldManager()
  59. class Meta:
  60. abstract = True
  61. verbose_name = _("Field")
  62. verbose_name_plural = _("Fields")
  63. def __str__(self):
  64. return self.label
  65. def get_choices(self):
  66. """
  67. Parse a comma separated choice string into a list of choices taking
  68. into account quoted choices.
  69. """
  70. choice = ""
  71. (quote, unquote) = ("`", "`")
  72. quoted = False
  73. for char in self.choices:
  74. if not quoted and char == quote:
  75. quoted = True
  76. elif quoted and char == unquote:
  77. quoted = False
  78. elif char == "," and not quoted:
  79. choice = choice.strip()
  80. if choice:
  81. yield choice, choice
  82. choice = ""
  83. else:
  84. choice += char
  85. choice = choice.strip()
  86. if choice:
  87. yield choice, choice
  88. def is_a(self, *args):
  89. """
  90. Helper that returns ``True`` if the field's type is given in any arg.
  91. """
  92. return self.field_type in args
  93. class Field(AbstractBaseField):
  94. form = models.ForeignKey("Form", related_name="fields")
  95. class Meta(AbstractBaseField.Meta):
  96. order_with_respect_to = "form"
  97. class FormEntry(models.Model):
  98. """
  99. An entry submitted via a user-built form.
  100. """
  101. form = models.ForeignKey("Form", related_name="entries")
  102. entry_time = models.DateTimeField(_("Date/time"))
  103. class Meta:
  104. verbose_name = _("Form entry")
  105. verbose_name_plural = _("Form entries")
  106. class FieldEntry(models.Model):
  107. """
  108. A single field value for a form entry submitted via a user-built form.
  109. """
  110. entry = models.ForeignKey("FormEntry", related_name="fields")
  111. field_id = models.IntegerField()
  112. value = models.CharField(max_length=settings.FORMS_FIELD_MAX_LENGTH,
  113. null=True)
  114. class Meta:
  115. verbose_name = _("Form field entry")
  116. verbose_name_plural = _("Form field entries")