from django.core.mail import send_mail, mail_managers
from django.core.validators import validate_email
from django import forms
+from django.db.models.fields.files import FieldFile
from django.template.loader import render_to_string
from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _
form_tag = None
form_type = 'create'
+ updatable = False
old_form_tags = []
form_title = _('Contact form')
submit_label = _('Submit')
mailing_field = None
mailing = False
data_processing = None
+ form_formsets = {}
+
+ disabled = False
+ disabled_template = None
required_css_class = 'required'
contact = NotImplemented
- def __init__(self, *args, **kwargs):
+ def __init__(self, data=None, files=None, *args, **kwargs):
self.instance = kwargs.pop('instance', None)
- super(ContactForm, self).__init__(*args, **kwargs)
+ if self.instance and (data is not None or files is not None):
+ for attachment in self.instance.attachment_set.all():
+ if attachment.tag not in files:
+ files[attachment.tag] = attachment.file
+ super(ContactForm, self).__init__(data, files, *args, **kwargs)
if not self.is_bound and self.instance:
- # files are omitted (not necessary for now)
self.fields['contact'].initial = self.instance.contact
body = self.instance.body
for field, value in body.iteritems():
if field in self.fields:
self.fields[field].initial = value
+ for attachment in self.instance.attachment_set.all():
+ self.fields[attachment.tag].initial = attachment
def get_dictionary(self, contact):
site = Site.objects.get_current()
'contact': contact,
}
+ @classmethod
+ def is_disabled(cls):
+ # end_time = localtime_to_utc(datetime(*cls.ends_on)) if cls.ends_on else None
+ # expired = end_time and end_time < timezone.now()
+ return cls.disabled # or expired
+
+ def formset_initial(self, prefix):
+ if not self.instance:
+ return None
+ return self.instance.body.get(prefix)
+
+ def get_formsets(self, request=None):
+ request_data = {'data': request.POST, 'files': request.FILES} if request else {}
+ kwargs_instance = dict(request_data)
+ kwargs_instance['instance'] = self.instance
+ formsets = {}
+ for prefix, formset_class in self.form_formsets.iteritems():
+ if getattr(formset_class, 'takes_instance', False):
+ kwargs = kwargs_instance
+ else:
+ kwargs = request_data
+ formsets[prefix] = formset_class(
+ prefix=prefix, initial=self.formset_initial(prefix), **kwargs)
+ return formsets
+
def save(self, request, formsets=None):
from .models import Attachment, Contact
body = {}
for name, value in self.cleaned_data.items():
- if not isinstance(value, UploadedFile) and name != 'contact':
+ if not isinstance(value, UploadedFile) and not isinstance(value, FieldFile) and name != 'contact':
body[name] = value
for formset in formsets or []:
ip=request.META['REMOTE_ADDR'],
contact=self.cleaned_data['contact'],
form_tag=self.form_tag)
+ contact.generate_key()
+ contact.save()
email_changed = True
- # not intended to be used with update forms
for name, value in self.cleaned_data.items():
if isinstance(value, UploadedFile):
+ Attachment.objects.filter(contact=contact, tag=name).delete() # delete files?
attachment = Attachment(contact=contact, tag=name)
attachment.file.save(value.name, value)
attachment.save()
--- /dev/null
+# -*- coding: utf-8 -*-
+from south.utils import datetime_utils as datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding field 'Contact.key'
+ db.add_column(u'contact_contact', 'key',
+ self.gf('django.db.models.fields.CharField')(default='#', max_length=30),
+ keep_default=False)
+
+
+ def backwards(self, orm):
+ # Deleting field 'Contact.key'
+ db.delete_column(u'contact_contact', 'key')
+
+
+ models = {
+ u'contact.attachment': {
+ 'Meta': {'object_name': 'Attachment'},
+ 'contact': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contact.Contact']"}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'tag': ('django.db.models.fields.CharField', [], {'max_length': '64'})
+ },
+ u'contact.contact': {
+ 'Meta': {'ordering': "('-created_at',)", 'object_name': 'Contact'},
+ 'body': ('jsonfield.fields.JSONField', [], {}),
+ 'contact': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'form_tag': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ip': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '30'})
+ }
+ }
+
+ complete_apps = ['contact']
\ No newline at end of file
# -*- coding: utf-8 -*-
import yaml
from hashlib import sha1
+import random
+import string
from django.db import models
from django.utils.encoding import smart_unicode, force_str
from django.db.models import permalink
from . import app_settings
+KEY_SIZE = 30
+
+
+def make_key(length):
+ return ''.join(
+ random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits)
+ for i in range(length))
+
+
class Contact(models.Model):
created_at = models.DateTimeField(_('submission date'), auto_now_add=True)
ip = models.IPAddressField(_('IP address'))
contact = models.CharField(_('contact'), max_length=128)
form_tag = models.CharField(_('form'), max_length=32, db_index=True)
body = JSONField(_('body'))
+ key = models.CharField(max_length=KEY_SIZE)
+
+ @classmethod
+ def generate_key(cls):
+ key = ''
+ while not key or cls.objects.filter(key=key).exists():
+ key = make_key(KEY_SIZE)
+ return key
@staticmethod
def pretty_print(value, for_html=False):
@permalink
def update_url(self):
- from contact.forms import update_forms, contact_forms
- form_class = update_forms.get(self.form_tag, contact_forms.get(self.form_tag))
- confirmation = form_class.confirmation_class.objects.get(contact=self)
- return 'edit_form', [], {'form_tag': self.form_tag, 'contact_id': self.id, 'key': confirmation.key}
+ return 'edit_form', [], {'form_tag': self.form_tag, 'contact_id': self.id, 'key': self.key}
class Attachment(models.Model):
def get_absolute_url(self):
return 'contact_attachment', [self.contact_id, self.tag]
+ @property
+ @models.permalink
+ def url(self):
+ return 'contact_attachment_key', [self.contact_id, self.tag, self.contact.key]
+
+ def __unicode__(self):
+ return self.file.name.rsplit('/', 1)[-1]
+
__import__(app_settings.FORMS_MODULE)
url(r'^(?P<form_tag>[^/]+)/edit/(?P<contact_id>[0-9]+)/(?P<key>[0-9a-zA-Z]+)/$', views.form, name='edit_form'),
url(r'^(?P<form_tag>[^/]+)/thanks/$', views.thanks, name='contact_thanks'),
url(r'^attachment/(?P<contact_id>\d+)/(?P<tag>[^/]+)/$', views.attachment, name='contact_attachment'),
+ url(r'^attachment/(?P<contact_id>\d+)/(?P<tag>[^/]+)/(?P<key>[0-9a-zA-Z]+)/$', views.attachment_key,
+ name='contact_attachment_key'),
url(r'^results/(?P<contact_id>\d+)/(?P<digest>[0-9a-f]+)/', views.results, name='contact_results'),
)
except KeyError:
raise Http404
if not (force_enabled and request.user.is_superuser):
- disabled = getattr(form_class, 'disabled', False)
- if disabled:
- template = getattr(form_class, 'disabled_template', None)
+ if form_class.is_disabled():
+ template = form_class.disabled_template
if template:
return render(request, template, {'title': form_class.form_title})
raise Http404
if contact_id:
contact = get_object_or_404(Contact, id=contact_id, form_tag=form_tag)
- if form_tag != 'olimpiada':
+ if not form_class.updatable:
raise Http404
if key != contact.key:
raise Http404
attachment = get_object_or_404(Attachment, contact_id=contact_id, tag=tag)
attachment_url = unquote(attachment.file.url)
return serve_file(attachment_url)
+
+
+def attachment_key(request, contact_id, tag, key):
+ contact = Contact.objects.get(id=contact_id)
+ if key != contact.key:
+ raise Http404
+ attachment = get_object_or_404(Attachment, contact_id=contact_id, tag=tag)
+ attachment_url = unquote(attachment.file.url)
+ return serve_file(attachment_url)