Skip to content

Commit

Permalink
Only showing 'clear' when field is optional #14
Browse files Browse the repository at this point in the history
Includes:
* Widget updates
* New test model + fixture data
* CSS tweaks
* New widget tests
  • Loading branch information
respondcreate committed May 19, 2015
1 parent 3220f05 commit 0a2cb47
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 26 deletions.
3 changes: 2 additions & 1 deletion tests/admin.py
Expand Up @@ -3,7 +3,7 @@

from versatileimagefield.widgets import VersatileImagePPOISelectWidget

from .models import VersatileImageTestModel
from .models import VersatileImageTestModel, VersatileImageWidgetTestModel


class VersatileImageTestModelForm(ModelForm):
Expand All @@ -27,3 +27,4 @@ class VersatileImageTestModelAdmin(admin.ModelAdmin):


admin.site.register(VersatileImageTestModel, VersatileImageTestModelAdmin)
admin.site.register(VersatileImageWidgetTestModel)
12 changes: 12 additions & 0 deletions tests/fixtures/versatileimagefield.json
Expand Up @@ -98,5 +98,17 @@
},
"model": "tests.versatileimagetestmodel",
"pk": 9
},
{
"fields": {
"image": "python-logo.png",
"image_no_ppoi": "python-logo.jpg",
"optional_image": "exif-orientation-examples/Landscape_8.jpg",
"optional_image_with_ppoi": "exif-orientation-examples/Landscape_6.jpg",
"ppoi": "0.5x0.5",
"optional_image_with_ppoi_ppoi": "1.0x1.0"
},
"model": "tests.versatileimagewidgettestmodel",
"pk": 1
}
]
22 changes: 22 additions & 0 deletions tests/models.py
Expand Up @@ -53,3 +53,25 @@ class VersatileImageTestModel(models.Model):
blank=True
)
ppoi = PPOIField()


class VersatileImageWidgetTestModel(models.Model):
"""A model for testing VersatileImageField widgets"""
image = VersatileImageField(
upload_to='./',
ppoi_field='ppoi',
)
image_no_ppoi = VersatileImageField(
upload_to='./',
)
optional_image = VersatileImageField(
upload_to='./',
blank=True
)
optional_image_with_ppoi = VersatileImageField(
upload_to='./',
blank=True,
ppoi_field='optional_image_with_ppoi_ppoi'
)
ppoi = PPOIField()
optional_image_with_ppoi_ppoi = PPOIField()
156 changes: 143 additions & 13 deletions tests/tests.py
Expand Up @@ -19,7 +19,7 @@
from django.test import Client, TestCase
from django.test.utils import override_settings
from django.utils._os import upath
from django.utils.six.moves import cPickle as pickle
from django.utils.six.moves import cPickle

from PIL import Image
from versatileimagefield.files import VersatileImageFileDescriptor
Expand Down Expand Up @@ -52,7 +52,7 @@
from versatileimagefield.versatileimagefield import CroppedImage, InvertImage

from .forms import VersatileImageTestModelForm
from .models import VersatileImageTestModel
from .models import VersatileImageTestModel, VersatileImageWidgetTestModel
from .serializers import VersatileImageTestModelSerializer


Expand All @@ -63,6 +63,7 @@ def setUp(self):
self.jpg = VersatileImageTestModel.objects.get(img_type='jpg')
self.png = VersatileImageTestModel.objects.get(img_type='png')
self.gif = VersatileImageTestModel.objects.get(img_type='gif')
self.widget_test = VersatileImageWidgetTestModel.objects.get(pk=1)
password = '12345'
user = User.objects.create_user(
username='test',
Expand Down Expand Up @@ -351,27 +352,156 @@ def test_widget_javascript(self):
Ensures the VersatileImagePPOIClickWidget widget loads appropriately
and its image preview is available
"""
response = self.client.get('/admin/tests/versatileimagetestmodel/1/')
response = self.client.get(
'/admin/tests/versatileimagewidgettestmodel/1/'
)
self.assertEqual(response.status_code, 200)
# Test required field with PPOI
self.assertInHTML(
(
"""
<div class="versatileimagefield">
<div class="sizedimage-mod initial">
<label class="versatileimagefield-label">Currently</label>
<a href="/media/python-logo.png">python-logo.png</a>
</div>
<div class="sizedimage-mod preview">
<label class="versatileimagefield-label">
Primary Point of Interest
</label>
<div class="image-wrap outer">
<div class="point-stage" id="image_0_point-stage"
data-image_preview_id="image_0_imagepreview">
<div class="ppoi-point" id="image_0_ppoi"></div>
</div>
<div class="image-wrap inner">
<img src="/media/__sized__/python-logo-thumbnail-300x300.png"
id="image_0_imagepreview"
data-hidden_field_id="id_image_1"
data-point_stage_id="image_0_point-stage"
data-ppoi_id="image_0_ppoi" class="sizedimage-preview"/>
</div>
</div>
</div>
<div class="sizedimage-mod new-upload">
<label class="versatileimagefield-label">Change</label>
<input class="file-chooser" id="id_image_0"
name="image_0" type="file" />
</div>
<input class="ppoi-input" id="id_image_1" name="image_1"
type="hidden" value="0.5x0.5" />
</div>
"""
),
str(response.content)
)
# Test required field no PPOI
self.assertInHTML(
(
"""
<div class="versatileimagefield">
<div class="sizedimage-mod initial">
<label class="versatileimagefield-label">Currently:</label>
<a href="/media/python-logo.jpg">python-logo.jpg</a>
</div>
<div class="sizedimage-mod new-upload">
<label class="versatileimagefield-label">Change:</label>
<input class="file-chooser" id="id_image_no_ppoi_0"
name="image_no_ppoi_0" type="file" />
</div>
<input class="ppoi-input" id="id_image_no_ppoi_1" name="image_no_ppoi_1"
type="hidden" value="0.5x0.5" />
</div>
"""
),
str(response.content)
)
# Test optional image no PPOI
self.assertInHTML(
(
"""
<div class="versatileimagefield">
<div class="sizedimage-mod initial">
<label class="versatileimagefield-label">Currently:</label>
<a href="/media/exif-orientation-examples/Landscape_8.jpg">
exif-orientation-examples/Landscape_8.jpg</a>
</div>
<div class="sizedimage-mod clear">
<input id="optional_image_0-clear_id" name="optional_image_0-clear"
type="checkbox" />
<label class="versatileimagefield-label"
for="optional_image_0-clear_id">Clear: </label>
</div>
<div class="sizedimage-mod new-upload">
<label class="versatileimagefield-label">Change:</label>
<input class="file-chooser" id="id_optional_image_0"
name="optional_image_0" type="file" />
</div>
<input class="ppoi-input" id="id_optional_image_1" name="optional_image_1"
type="hidden" value="0.5x0.5" />
</div>
"""
),
str(response.content)
)
# Test optional image with PPOI
self.assertInHTML(
(
'<img src="/media/__sized__/python-logo-thumbnail-300x300.png"'
' id="image_0_imagepreview" data-hidden_field_id="id_image_1"'
' data-point_stage_id="image_0_point-stage" '
'data-ppoi_id="image_0_ppoi" class="sizedimage-preview"/>'
"""
<div class="versatileimagefield">
<div class="sizedimage-mod initial">
<label class="versatileimagefield-label">Currently</label>
<a href="/media/exif-orientation-examples/Landscape_6.jpg">
exif-orientation-examples/Landscape_6.jpg</a>
</div>
<div class="sizedimage-mod clear">
<input id="optional_image_with_ppoi_0-clear_id"
name="optional_image_with_ppoi_0-clear" type="checkbox" />
<label class="versatileimagefield-label" for="optional_image_with_ppoi_0-clear_id">
Clear: </label>
</div>
<div class="sizedimage-mod preview">
<label class="versatileimagefield-label">
Primary Point of Interest</label>
<div class="image-wrap outer">
<div class="point-stage"
id="optional_image_with_ppoi_0_point-stage"
data-image_preview_id="optional_image_with_ppoi_0_imagepreview">
<div class="ppoi-point" id="optional_image_with_ppoi_0_ppoi"></div>
</div>
<div class="image-wrap inner">
<img src="/media/__sized__/exif-orientation-examples/Landscape_6-thumbnail-300x300.jpg"
id="optional_image_with_ppoi_0_imagepreview"
data-hidden_field_id="id_optional_image_with_ppoi_1"
data-point_stage_id="optional_image_with_ppoi_0_point-stage"
data-ppoi_id="optional_image_with_ppoi_0_ppoi" class="sizedimage-preview"/>
</div>
</div>
</div>
<div class="sizedimage-mod new-upload">
<label class="versatileimagefield-label">Change</label>
<input class="file-chooser" id="id_optional_image_with_ppoi_0" name="optional_image_with_ppoi_0" type="file" />
</div>
<input class="ppoi-input" id="id_optional_image_with_ppoi_1"
name="optional_image_with_ppoi_1" type="hidden" value="1.0x1.0" />
</div>
"""
),
str(response.content)
)
# Test that javascript loads correctly
self.assertInHTML(
(
'<script type="text/javascript" src="/static/'
'versatileimagefield/js/versatileimagefield.js"></script>'
'<script type="text/javascript" '
'src="/static/versatileimagefield/js/versatileimagefield.js">'
'</script>'
),
str(response.content)
)
self.assertTrue(
self.png.image.field.storage.exists(
self.png.image.thumbnail['300x300'].name
self.widget_test.image.field.storage.exists(
self.widget_test.image.thumbnail['300x300'].name
)
)

Expand Down Expand Up @@ -406,11 +536,11 @@ def test_VersatileImageField_picklability(self):
"""
Ensures VersatileImageField instances can be pickled/unpickled.
"""
pickle.dump(
cPickle.dump(
self.jpg,
open("pickletest.p", "wb")
)
jpg_unpickled = pickle.load(
jpg_unpickled = cPickle.load(
open("pickletest.p", "rb")
)
jpg_instance = jpg_unpickled
Expand Down
Expand Up @@ -2,18 +2,15 @@ div.versatileimagefield {
float:left;
clear:right;
display:block;
min-width:350px;
}

label.versatileimagefield-label {
display:block;
display:inline;
float:left;
clear:right;
font-weight:bold !important;
clear:both;
font-size:1em;
}

label.versatileimagefield-label:after {
content:": ";
padding-top:0px;
}

div.sizedimage-mod {
Expand All @@ -27,3 +24,9 @@ div.image-wrap.outer {
div.sizedimage-mod:first-child {
margin-top:0;
}
div.versatileimagefield input[type='file'] {
margin-top:0px;
margin-bottom:0px;
padding-top:0px;
padding-bottom:0px;
}
21 changes: 16 additions & 5 deletions versatileimagefield/widgets.py
Expand Up @@ -25,19 +25,30 @@

class ClearableFileInputWithImagePreview(ClearableFileInput):
ppoi_label = ugettext_lazy('Primary Point of Interest')
template_with_initial = (
'<div class="sizedimage-mod initial">'
'<label class="versatileimagefield-label">'
'%(initial_text)s:</label> %(initial)s '
'</div>'
'%(clear_template)s'
'<div class="sizedimage-mod new-upload">'
'<label class="versatileimagefield-label">%(input_text)s:</label>'
'%(input)s'
'</div>'
)
template_with_clear = (
'<div class="sizedimage-mod clear">'
'%(clear)s <label class="versatileimagefield-label" '
'for="%(clear_checkbox_id)s">'
'%(clear_checkbox_label)s</label>'
'%(clear_checkbox_label)s: </label>'
'</div>'
)
template_with_initial_and_imagepreview = """
<div class="sizedimage-mod initial">
<label class="versatileimagefield-label">%(initial_text)s</label>
%(initial)s
</div>
<div class="sizedimage-mod clear">
%(clear_template)s
</div>
%(clear_template)s
<div class="sizedimage-mod preview">
<label class="versatileimagefield-label">%(ppoi_label)s</label>
<div class="image-wrap outer">
Expand Down Expand Up @@ -125,7 +136,7 @@ def render(self, name, value, attrs=None):
else:
template = self.template_with_initial

if not self.is_required:
if value.field.blank:
checkbox_name = self.clear_checkbox_name(name)
checkbox_id = self.clear_checkbox_id(checkbox_name)
substitutions['clear_checkbox_name'] = conditional_escape(
Expand Down

0 comments on commit 0a2cb47

Please sign in to comment.