/ella/sendmail/forms.py

https://github.com/strogo/ella · Python · 138 lines · 81 code · 30 blank · 27 comment · 7 complexity · 6951feedcdcbac210b0e512bb8596c48 MD5 · raw file

  1. from datetime import datetime
  2. import time
  3. import logging
  4. from hashlib import md5
  5. from django.conf import settings
  6. from django.db import models
  7. from django.contrib.contenttypes.models import ContentType
  8. from django import forms
  9. from django.utils.translation import ugettext_lazy as _
  10. from ella.core.cache import get_cached_object
  11. INIT_PROPS = {
  12. 'target': '',
  13. 'gonzo': '',
  14. }
  15. log = logging.getLogger('ella.sendmail')
  16. def compute_hash(target='', timestamp=''):
  17. """
  18. counts md5 hash of options
  19. this is simple check, if sent data are the same as expected
  20. (defined in options)
  21. """
  22. timestamp = str(timestamp)
  23. return md5('-'.join((target, timestamp, settings.SECRET_KEY,))).hexdigest()
  24. class SendMailForm(forms.Form):
  25. def __init__(self, data=None, init_props=INIT_PROPS, **kwargs):
  26. super(SendMailForm, self).__init__(data=data, **kwargs)
  27. self.set_init_props(data, init_props)
  28. self.init_form(self.init_props)
  29. if not data:
  30. self.fill_form_values()
  31. def set_init_props(self, data=None, init_props=INIT_PROPS):
  32. """set initial form properties
  33. form is created from data, if it is bound
  34. from init_props, if not bound
  35. from options saved in database, if any
  36. """
  37. if data:
  38. # don't want MultiValueDict here - sorry for this hack - FIXME
  39. init_props = dict(zip(data.keys(), data.values()))
  40. # copy defalt settings
  41. self.init_props = INIT_PROPS.copy()
  42. # set actual time
  43. now = int(time.mktime(datetime.now().timetuple()))
  44. self.init_props['timestamp'] = now
  45. # update defaults with form init params
  46. self.init_props.update(init_props)
  47. target_ct, target_id = None, None
  48. try:
  49. target_ct, target_id = self.init_props['target'].split(':')
  50. target_ct, target_id = int(target_ct), int(target_id)
  51. target_contenttype = get_cached_object(ContentType, pk=target_ct)
  52. self.target_object = get_cached_object(target_contenttype, pk=target_id)
  53. except ValueError, ve:
  54. log.error('ValueError: %s' % str(ve))
  55. except models.ObjectDoesNotExist, e:
  56. log.error('Object does not exist: %s' % str(e))
  57. # defaults for this instance
  58. self.init_props['target_ct'] = target_ct
  59. self.init_props['target_id'] = target_id
  60. # defaults continue
  61. #self.init_props['gonzo'] = compute_hash(self.init_props['target'], self.init_props['timestamp'])
  62. self.init_props['gonzo'] = compute_hash(self.init_props['target'])
  63. def init_form(self, init_props={}):
  64. """create form by given init_props"""
  65. self.add_hidden_inputs()
  66. self.add_normal_inputs()
  67. # self.arrange_form_by_opts()
  68. def add_hidden_inputs(self):
  69. """new hidden input fields, without initial values"""
  70. hidden = forms.HiddenInput()
  71. self.fields['gonzo'] = forms.RegexField(self.init_props['gonzo'], widget=hidden)
  72. self.fields['target'] = forms.RegexField(r'\d+%s\d+' % ':', max_length=128, widget=hidden)
  73. self.fields['timestamp'] = forms.IntegerField(widget=hidden)
  74. def add_normal_inputs(self):
  75. """any other normal inputs"""
  76. textarea = forms.Textarea()
  77. self.fields['sender_mail'] = forms.EmailField(label=_("Sender email:"))
  78. self.fields['sender_name'] = forms.CharField(max_length=40, required=False, label=_("Sender name:"))
  79. self.fields['recipient_mail'] = forms.EmailField(label=_("Recipient email:"))
  80. self.fields['custom_message'] = forms.CharField(max_length=300, required=False, widget=textarea, label=_("Email message:"))
  81. def fill_form_values(self):
  82. """fill form initial values - only for nonbound form"""
  83. # TODO: maybe add decorator for nonbound validation ???
  84. self.fields['gonzo'].initial = self.init_props['gonzo']
  85. self.fields['target'].initial = self.init_props['target']
  86. self.fields['timestamp'].initial = self.init_props['timestamp']
  87. def clean(self):
  88. """registered user validation and other cleaning"""
  89. from django.forms.util import ValidationError
  90. try:
  91. # target_ct, target_id validation
  92. target_ct = self.init_props['target_ct']
  93. target_id = self.init_props['target_id']
  94. target_ct = get_cached_object(ContentType, pk=target_ct)
  95. target_object = get_cached_object(target_ct, pk=target_id)
  96. self.cleaned_data['target_ct'] = target_ct
  97. self.cleaned_data['target_id'] = target_id
  98. self.cleaned_data['target_object'] = target_object
  99. except models.ObjectDoesNotExist:
  100. raise ValidationError, _("Target object does not exist.")
  101. return self.cleaned_data
  102. class SendBuddyForm(SendMailForm):
  103. def add_normal_inputs(self):
  104. """any other normal inputs"""
  105. self.fields['sender_mail'] = forms.EmailField(label=_("Sender email:"))
  106. self.fields['recipient_mail'] = forms.EmailField(label=_("Recipient email:"))
  107. self.fields['sender_name'] = forms.CharField(max_length=40, required=False, label=_("Sender name:"))