fix after merge
authorJan Szejko <janek37@gmail.com>
Tue, 4 Dec 2018 16:40:35 +0000 (17:40 +0100)
committerJan Szejko <janek37@gmail.com>
Tue, 4 Dec 2018 16:40:35 +0000 (17:40 +0100)
contact/forms.py
contact/migrations/0003_auto__add_field_contact_key.py [new file with mode: 0644]
contact/models.py
contact/urls.py
contact/views.py

index 73be1db..a9e3366 100644 (file)
@@ -5,6 +5,7 @@ from django.core.files.uploadedfile import UploadedFile
 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 _
@@ -39,6 +40,7 @@ class ContactForm(forms.Form):
 
     form_tag = None
     form_type = 'create'
+    updatable = False
     old_form_tags = []
     form_title = _('Contact form')
     submit_label = _('Submit')
@@ -47,20 +49,29 @@ class ContactForm(forms.Form):
     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()
@@ -71,11 +82,36 @@ class ContactForm(forms.Form):
             '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 []:
@@ -100,10 +136,12 @@ class ContactForm(forms.Form):
                 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()
diff --git a/contact/migrations/0003_auto__add_field_contact_key.py b/contact/migrations/0003_auto__add_field_contact_key.py
new file mode 100644 (file)
index 0000000..d9347a4
--- /dev/null
@@ -0,0 +1,42 @@
+# -*- 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
index f07b33a..fb8c8ac 100644 (file)
@@ -1,6 +1,8 @@
 # -*- 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
@@ -9,12 +11,29 @@ from jsonfield import JSONField
 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):
@@ -40,10 +59,7 @@ class Contact(models.Model):
 
     @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):
@@ -55,5 +71,13 @@ 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)
index b0866ed..ed6f49c 100644 (file)
@@ -8,5 +8,7 @@ urlpatterns = patterns(
     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'),
 )
index 0316b20..580a65d 100644 (file)
@@ -24,15 +24,14 @@ def form(request, form_tag, force_enabled=False, contact_id=None, key=None):
     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
@@ -93,3 +92,12 @@ def attachment(request, contact_id, tag):
     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)