Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRogelio Mita <rogeliomita@activitycentral.com>2013-07-31 00:45:17 (GMT)
committer Rogelio Mita <rogeliomita@activitycentral.com>2013-07-31 02:18:06 (GMT)
commit4cf5c2b581d12dd8c23efcf7c7b667e9e4efde80 (patch)
tree82a38aea5c67c165acbfb140d35523168cd8a655
parent9b17f03e8ab9e40e95b87f595b8c81bea1272fcb (diff)
Save image for a field
-rw-r--r--.gitignore2
-rw-r--r--webapp/coffee/factoryField.coffee3
-rw-r--r--webapp/js_tests/fixtures/container.html1
-rw-r--r--webapp/polls/models.py85
-rw-r--r--webapp/polls/templates/mustache/field.html4
-rw-r--r--webapp/polls/templates/tags/structure.html2
-rw-r--r--webapp/polls/templatetags/poll_tags.py4
-rw-r--r--webapp/polls/tests/field_tests.py25
-rw-r--r--webapp/polls/tests/structure_tests.py10
-rw-r--r--webapp/polls/views.py2
-rw-r--r--webapp/webapp/media/images/empty0
-rw-r--r--webapp/webapp/settings.py4
-rw-r--r--webapp/webapp/static/js/factoryField.js3
13 files changed, 133 insertions, 12 deletions
diff --git a/.gitignore b/.gitignore
index aa2da63..ec9d821 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,8 @@
webapp/webapp/media/cache/
webapp/webapp/media/image_options/*
!webapp/webapp/media/image_options/empty
+webapp/webapp/media/images/*
+!webapp/webapp/media/images/empty
webapp/webapp/env_settings.py
database.db
webapp/webapp/media/results_bck/*
diff --git a/webapp/coffee/factoryField.coffee b/webapp/coffee/factoryField.coffee
index b24d07c..ccba883 100644
--- a/webapp/coffee/factoryField.coffee
+++ b/webapp/coffee/factoryField.coffee
@@ -49,7 +49,8 @@ factoryField = (order, value) ->
"visible_errors": errors.length,
"WIDGET_TYPES": widget_types,
"dependence_forms": dependence_forms,
- "img_src": value['img_src']
+ "img_src": IMAGE_MEDIA_URL + "/" + value['img'],
+ "img_name": value['img'],
}
)
)
diff --git a/webapp/js_tests/fixtures/container.html b/webapp/js_tests/fixtures/container.html
index d1b1cc1..64e27d3 100644
--- a/webapp/js_tests/fixtures/container.html
+++ b/webapp/js_tests/fixtures/container.html
@@ -24,5 +24,6 @@
OFFSET_OPTION_ID = 0,
WITH_IMAGES = ["ImageCheckBox", "ImageRadioButton"],
IMAGE_OPTIONS_TMP_MEDIA_URL,
+ IMAGE_MEDIA_URL,
POLL_ID;
</script> \ No newline at end of file
diff --git a/webapp/polls/models.py b/webapp/polls/models.py
index 7c657cb..f4d9ed1 100644
--- a/webapp/polls/models.py
+++ b/webapp/polls/models.py
@@ -669,6 +669,7 @@ class Field(AbstractObject, ComponentStructure):
self.order = int(order) if order else order
self.name = data.get('name', None)
self.img = data.get('img', None)
+ self.uploaded_file = data.get("uploaded_file", None)
value = data.get('dependence', None)
self.dependence = value
@@ -735,6 +736,13 @@ class Field(AbstractObject, ComponentStructure):
if img and opt not in self.options:
self.options.append(opt)
+ def img_validate(self, img_file):
+ try:
+ ImageField().to_python(img_file)
+ except DjangoValidationError, e:
+ self.img = None
+ raise Field.ValidationError(e.messages[0])
+
def validate(self, options=[], new_data=None):
self.errors = []
rule, msg = Field.VALIDATION_RULES.get(self.widget_type)
@@ -797,9 +805,32 @@ class Field(AbstractObject, ComponentStructure):
msg = "Necesita ingresar una pregunta"
self.errors.append(msg)
+ if self.uploaded_file:
+ try:
+ self.img_validate(self.uploaded_file)
+ except Field.ValidationError:
+ self.errors.append(u"Pregunta con imagen no válida.")
+
if len(self.errors):
raise Field.ValidationError(str(self.errors))
+ def storing_image(self, path, img_file):
+ img_path = path + '/%s' % img_file.name
+ if os.path.exists(img_path):
+ os.remove(img_path)
+
+ with open(img_path, 'wb+') as dst:
+ for chunk in img_file.chunks():
+ dst.write(chunk)
+ dst.close()
+
+ def store_image(self, path):
+ if self.uploaded_file:
+ self.storing_image(path, self.uploaded_file)
+
+ def get_img_name(self):
+ return getattr(self.uploaded_file, "name", self.img)
+
def to_python(self, with_errors=False, img_serialize=False):
data = {}
@@ -811,6 +842,10 @@ class Field(AbstractObject, ComponentStructure):
if self.dependence:
data.update({'dependence': self.dependence})
+ img_name = self.get_img_name()
+ if img_name:
+ data.update({"img": img_name})
+
if with_errors:
data.update({'errors': self.errors})
@@ -969,10 +1004,22 @@ class Structure(AbstractObject, ComponentStructure):
return options
+ def get_image_media_url(self):
+ return settings.IMAGES_MEDIA_URL + '/%s' % self.poll_id
+
def get_image_options(self):
options = self.get_options()
return filter(lambda opt: opt.img_name is not None, options)
+ def get_images_fields(self):
+ fields = []
+ for group in self.groups:
+ for field in group.fields:
+ fields.append(field)
+
+ fields = filter(lambda opt: field.get_img_name() is not None, fields)
+ return [field.get_img_name() for field in fields]
+
def validate(self):
self.errors = []
@@ -1042,8 +1089,6 @@ class Structure(AbstractObject, ComponentStructure):
if self.id:
_dict.update({'_id': ObjectId(self.id)})
- print _dict
-
# Save process -> Update if it has an id, else insert
structure_id = get_db().structures.save(_dict)
@@ -1058,6 +1103,16 @@ class Structure(AbstractObject, ComponentStructure):
except:
pass
+ # Removing older img files
+ current_img_fields = self.get_images_fields()
+ path = self.get_image_path()
+ for file in os.listdir(path):
+ if file not in current_img_fields:
+ try:
+ os.remove("%s/%s" % (path, file))
+ except:
+ pass
+
return structure_id
@staticmethod
@@ -1118,6 +1173,32 @@ class Structure(AbstractObject, ComponentStructure):
dst.write(chunk)
dst.close()
+ def get_image_tmp_path(self):
+ path = settings.IMAGES_ROOT + '/%s/tmp' % self.poll_id
+
+ try:
+ os.makedirs(path)
+ except OSError:
+ pass
+
+ return path
+
+ def get_image_path(self):
+ path = settings.IMAGES_ROOT + '/%s' % self.poll_id
+
+ try:
+ os.makedirs(path)
+ except OSError:
+ pass
+
+ return path
+
+ def save_image_fields(self):
+
+ for group in self.groups:
+ for field in group.fields:
+ field.store_image(path=self.get_image_path())
+
def save_image_options(self, tmp=False):
options = self.get_options()
diff --git a/webapp/polls/templates/mustache/field.html b/webapp/polls/templates/mustache/field.html
index a967893..07a5766 100644
--- a/webapp/polls/templates/mustache/field.html
+++ b/webapp/polls/templates/mustache/field.html
@@ -49,6 +49,8 @@
value="[[ name ]]"
placeholder="Pregunta..." />
+ <input type="hidden" name="groups.[[ group_order ]].fields.[[ order ]].img" value="[[ img_name ]]" />
+
<div class="fileupload fileupload-new" data-provides="fileupload">
<div class="fileupload-new thumbnail" style="width: 50px; height: 50px;">
<img src="[[ img_src ]]" /></div>
@@ -56,7 +58,7 @@
<span class="btn btn-file">
<span class="fileupload-new">Elegir imagen</span>
<span class="fileupload-exists">Change</span>
- <input type="file" name="groups.[[ group_order ]].fields.[[ order ]].img"/>
+ <input type="file" name="groups.[[ group_order ]].fields.[[ order ]].uploaded_file" />
</span>
<a href="#" class="btn fileupload-exists" data-dismiss="fileupload">Remove</a>
</div>
diff --git a/webapp/polls/templates/tags/structure.html b/webapp/polls/templates/tags/structure.html
index efe46d9..61e0c63 100644
--- a/webapp/polls/templates/tags/structure.html
+++ b/webapp/polls/templates/tags/structure.html
@@ -43,8 +43,8 @@
WITH_IMAGES = {{ WITH_IMAGES|json }},
OFFSET_OPTION_ID = {{ OFFSET_OPTION_ID|json }},
IMAGE_OPTIONS_TMP_MEDIA_URL = {{ IMAGE_OPTIONS_TMP_MEDIA_URL|json }},
+ IMAGE_MEDIA_URL = {{ IMAGE_MEDIA_URL|json }},
POLL_ID = {{ POLL_ID|json }};
-
</script>
diff --git a/webapp/polls/templatetags/poll_tags.py b/webapp/polls/templatetags/poll_tags.py
index c28d237..5cbb284 100644
--- a/webapp/polls/templatetags/poll_tags.py
+++ b/webapp/polls/templatetags/poll_tags.py
@@ -11,6 +11,7 @@ register = template.Library()
def render_structure(context, structure):
structure_data = structure.to_python(with_errors=True)
IMAGE_OPTIONS_TMP_MEDIA_URL = structure.get_image_options_tmp_media_url()
+ IMAGE_MEDIA_URL = structure.get_image_media_url()
return render_to_string(
'tags/structure.html',
@@ -22,7 +23,8 @@ def render_structure(context, structure):
"OFFSET_OPTION_ID": Field.get_offset_id(),
"IMAGE_OPTIONS_TMP_MEDIA_URL": IMAGE_OPTIONS_TMP_MEDIA_URL,
"POLL_ID": str(context['poll'].id),
- "groups": structure_data.get("groups", {})
+ "groups": structure_data.get("groups", {}),
+ "IMAGE_MEDIA_URL": IMAGE_MEDIA_URL
}
)
diff --git a/webapp/polls/tests/field_tests.py b/webapp/polls/tests/field_tests.py
index b7c6a18..8609357 100644
--- a/webapp/polls/tests/field_tests.py
+++ b/webapp/polls/tests/field_tests.py
@@ -4,7 +4,7 @@ from django.test import TestCase
from polls.models import (
Poll, Dependence, Field, WIDGET_TYPES, WITH_OPTIONS, WITH_IMAGES)
-from utils.test import MongoTestCase, mock_in_memory_image
+from utils.test import MongoTestCase, mock_in_memory_image, mock_text_file
class DependenceTests(TestCase):
@@ -240,6 +240,19 @@ class FieldTests(MongoTestCase):
self.assertRaises(Field.ValidationError, self.field.validate)
self.assertEqual(1, len(self.field.errors))
+ def test_to_python_with_img_name(self):
+
+ data = {
+ 'order': 0,
+ 'name': "field_0",
+ }
+ field = Field(data=data)
+ field.img = 'img_name'
+
+ to_python = field.to_python()['0']
+ self.assertTrue('img' in to_python.keys())
+ self.assertEqual('img_name', to_python['img'])
+
def test_to_python(self):
# Widget_type = TextInput
@@ -384,3 +397,13 @@ class FieldTests(MongoTestCase):
'values': ['ID', 'AND', 'ID']
}
self.assertEqual(expected, field.dependence)
+
+ def test_image_validation(self):
+ invalid_img_file = mock_text_file()
+
+ data = {'id': '0', 'name': 'name', 'img': invalid_img_file}
+ field = Field(data)
+
+ img_validate = lambda: field.img_validate(invalid_img_file)
+ self.assertRaises(Field.ValidationError, img_validate)
+ self.assertIsNone(field.img)
diff --git a/webapp/polls/tests/structure_tests.py b/webapp/polls/tests/structure_tests.py
index c4081fb..cd10d56 100644
--- a/webapp/polls/tests/structure_tests.py
+++ b/webapp/polls/tests/structure_tests.py
@@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
from polls.models import Poll, Group, Field, Structure
-from utils.test import MongoTestCase
+from utils.test import MongoTestCase, mock_in_memory_image
class StructureTests(MongoTestCase):
@@ -252,14 +252,16 @@ class StructureTests(MongoTestCase):
self.assertEqual(img, structure.groups[0].fields[0].img)
def test_save_field_image(self):
- img = "soy una imagen de verdad!!"
+ img_name = "img_test.jpg"
+ img = mock_in_memory_image(name=img_name)
poll = self.poll
data = self.data
- data['groups']['0']['fields']['0']['img'] = img
+ data['groups']['0']['fields']['0']['uploaded_file'] = img
structure = Structure(data=data, poll=poll)
s_id = structure.save()
structure = Structure.get(id=s_id)
- self.assertEqual(img, structure.groups[0].fields[0].img)
+ self.assertEqual(
+ img_name, structure.groups[0].fields[0].get_img_name())
diff --git a/webapp/polls/views.py b/webapp/polls/views.py
index 9a5a631..a2239a3 100644
--- a/webapp/polls/views.py
+++ b/webapp/polls/views.py
@@ -230,6 +230,7 @@ class StructureFormView(TemplateView):
if structure.is_valid(new_data=data):
try:
structure.save_image_options(tmp=False)
+ structure.save_image_fields()
structure.save()
except Exception:
msg = u'Ocurrió un error, no se guardó la estructura.'
@@ -254,6 +255,7 @@ class StructureFormView(TemplateView):
)
else:
structure.save_image_options(tmp=True)
+ structure.save_image_fields()
context.update({'errors': structure.errors})
messages.add_message(
self.request,
diff --git a/webapp/webapp/media/images/empty b/webapp/webapp/media/images/empty
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/webapp/webapp/media/images/empty
diff --git a/webapp/webapp/settings.py b/webapp/webapp/settings.py
index 218ed8a..afdde63 100644
--- a/webapp/webapp/settings.py
+++ b/webapp/webapp/settings.py
@@ -208,10 +208,14 @@ JASMINE_TEST_DIRECTORY = PROJECT_ROOT + '/../js_tests/'
IMAGE_OPTIONS_ROOT = MEDIA_ROOT + 'image_options'
+IMAGES_ROOT = MEDIA_ROOT + 'images'
+
RESULT_BCK_ROOT = MEDIA_ROOT + 'results_bck'
IMAGE_OPTIONS_MEDIA_URL = MEDIA_URL + 'image_options'
+IMAGES_MEDIA_URL = MEDIA_URL + 'images'
+
THUMBNAIL_DEBUG = True
try:
diff --git a/webapp/webapp/static/js/factoryField.js b/webapp/webapp/static/js/factoryField.js
index 1834e49..c5b98bd 100644
--- a/webapp/webapp/static/js/factoryField.js
+++ b/webapp/webapp/static/js/factoryField.js
@@ -58,7 +58,8 @@
"visible_errors": errors.length,
"WIDGET_TYPES": widget_types,
"dependence_forms": dependence_forms,
- "img_src": value['img_src']
+ "img_src": IMAGE_MEDIA_URL + "/" + value['img'],
+ "img_name": value['img']
}));
remove_button = field_widget.find('.WField_remove');
bindFieldRemoveButton(remove_button);