def test_prefetch_related_through_table(self): author = Author.objects.create(name="Author") for x in range(10): article = Article.objects.create( title="prefetch", author=author, lead_image=self.create_unique_image('img.jpg'), alt_image=self.create_unique_image('img.png')) article.lead_image.generate_thumbs() article.alt_image.generate_thumbs() lead_sizes = [s.name for s in Size.flatten(Article.LEAD_IMAGE_SIZES)] alt_sizes = [s.name for s in Size.flatten(Article.ALT_IMAGE_SIZES)] with self.assertNumQueries(6): authors = Author.objects.filter(pk=author.pk).prefetch_related( 'article_set__lead_image__thumbs', 'article_set__alt_image__thumbs') for author in authors: for article in author.article_set.all(): self.assertTrue(article.lead_image.name.endswith('jpg')) self.assertTrue(article.alt_image.name.endswith('png')) for thumb in article.lead_image.related_object.thumbs.all( ): self.assertIn(thumb.name, lead_sizes) for thumb in article.alt_image.related_object.thumbs.all(): self.assertIn(thumb.name, alt_sizes)
def test_prefetch_related_through_table(self): author = Author.objects.create(name="Author") for x in range(10): article = Article.objects.create( title="prefetch", author=author, lead_image=self.create_unique_image('img.jpg'), alt_image=self.create_unique_image('img.png')) article.lead_image.generate_thumbs() article.alt_image.generate_thumbs() lead_sizes = [s.name for s in Size.flatten(Article.LEAD_IMAGE_SIZES)] alt_sizes = [s.name for s in Size.flatten(Article.ALT_IMAGE_SIZES)] with self.assertNumQueries(6): authors = Author.objects.filter(pk=author.pk).prefetch_related( 'article_set__lead_image__thumbs', 'article_set__alt_image__thumbs') for author in authors: for article in author.article_set.all(): self.assertTrue(article.lead_image.path.endswith('jpg')) self.assertTrue(article.alt_image.path.endswith('png')) for thumb in article.lead_image.related_object.thumbs.all(): self.assertIn(thumb.name, lead_sizes) for thumb in article.alt_image.related_object.thumbs.all(): self.assertIn(thumb.name, alt_sizes)
def sizes(self): size = getattr(self.image_file.metadata, 'crop_size', None) if not size: size = Size('crop', max_w=self.max_w) else: size.max_w = self.max_w return [size]
def test_prefetch_related_with_alt_images(self): img_map = {} for x in range(3): lead_image_path = self.create_unique_image('img.jpg') alt_image_path = self.create_unique_image('img.jpg') article = Article.objects.create(title="", author=self.author, lead_image=lead_image_path, alt_image=alt_image_path) article.lead_image.generate_thumbs() article.alt_image.generate_thumbs() img_map[article.pk] = (lead_image_path, alt_image_path) with self.assertNumQueries(5): articles = (Article.objects.filter(id__in=img_map.keys()) .prefetch_related('lead_image__thumbs', 'alt_image__thumbs')) for article in articles: lead_name, alt_name = img_map[article.pk] self.assertEqual(lead_name, article.lead_image.related_object.image.name) self.assertEqual(alt_name, article.alt_image.related_object.image.name) lead_sizes = [s.name for s in Size.flatten(Article.LEAD_IMAGE_SIZES)] lead_thumbs = list(article.lead_image.related_object.thumbs.all()) self.assertEqual(len(lead_thumbs), len(lead_sizes)) for thumb in lead_thumbs: self.assertEqual(thumb.image_id, article.lead_image.related_object.pk) self.assertIn(thumb.name, lead_sizes) alt_sizes = [s.name for s in Size.flatten(Article.ALT_IMAGE_SIZES)] alt_thumbs = list(article.alt_image.related_object.thumbs.all()) self.assertEqual(len(alt_thumbs), len(alt_sizes)) for thumb in alt_thumbs: self.assertEqual(thumb.image_id, article.alt_image.related_object.pk) self.assertIn(thumb.name, alt_sizes)
class Author(models.Model): name = models.CharField(max_length=255) HEADSHOT_SIZES = [ Size('main', w=220, h=180, auto=[ Size('thumb', w=110, h=90), ]), ] headshot = CropDusterField(upload_to="author/headshots/%Y/%m", sizes=HEADSHOT_SIZES, related_name="author_headshotset")
def test_addform_multiple_image(self): author = Author.objects.create(name="Mark Twain") self.load_admin(Article) browser = self.selenium browser.find_element_by_id('id_title').send_keys( "A Connecticut Yankee in King Arthur's Court") # Upload and crop first Image browser.find_element_by_css_selector( '#lead_image-group .cropduster-button').click() with self.switch_to_popup_window(): with self.visible_selector('#id_image') as el: el.send_keys(os.path.join(self.TEST_IMG_DIR, 'img.jpg')) with self.clickable_selector('#upload-button') as el: el.click() with self.clickable_selector('#crop-button') as el: el.click() with self.clickable_selector('#crop-button:not(.disabled)') as el: el.click() # Upload and crop second Image with self.clickable_selector( '#alt_image-group .cropduster-button') as el: # With the Chrome driver, using Grappelli, this button can be covered # by the fixed footer. So we scroll the button into view. browser.execute_script('window.scrollTo(0, %d)' % el.location['y']) el.click() with self.switch_to_popup_window(): with self.visible_selector('#id_image') as el: el.send_keys(os.path.join(self.TEST_IMG_DIR, 'img.png')) with self.clickable_selector('#upload-button') as el: el.click() with self.clickable_selector('#crop-button') as el: el.click() # Add required FK browser.find_element_by_xpath( '//select[@id="id_author"]/option[@value=%d]' % author.pk).click() self.save_form() # Test that crops saved correctly article = Article.objects.all()[0] lead_sizes = list(Size.flatten(Article.LEAD_IMAGE_SIZES)) alt_sizes = list(Size.flatten(Article.ALT_IMAGE_SIZES)) self.assertTrue(article.lead_image.name.endswith('.jpg')) self.assertEqual(len(article.lead_image.related_object.thumbs.all()), len(lead_sizes)) self.assertTrue(article.alt_image.name.endswith('.png')) self.assertEqual(len(article.alt_image.related_object.thumbs.all()), len(alt_sizes))
class OptionalSizes(models.Model): TEST_SIZES = [ Size('main', w=600, h=480, auto=[ Size('optional', w=1200, h=960, required=False), ]) ] slug = models.SlugField() image = CropDusterField(upload_to="test", sizes=TEST_SIZES)
def test_addform_multiple_image(self): author = Author.objects.create(name="Mark Twain") self.load_admin(Article) browser = self.selenium browser.find_element_by_id('id_title').send_keys("A Connecticut Yankee in King Arthur's Court") # Upload and crop first Image browser.find_element_by_css_selector('#lead_image-group .cropduster-button').click() with self.switch_to_popup_window(): with self.visible_selector('#id_image') as el: el.send_keys(os.path.join(self.TEST_IMG_DIR, 'img.jpg')) with self.clickable_selector('#upload-button') as el: el.click() with self.clickable_selector('#crop-button') as el: el.click() with self.clickable_selector('#crop-button:not(.disabled)') as el: el.click() # Upload and crop second Image with self.clickable_selector('#alt_image-group .cropduster-button') as el: # With the Chrome driver, using Grappelli, this button can be covered # by the fixed footer. So we scroll the button into view. browser.execute_script('window.scrollTo(0, %d)' % el.location['y']) el.click() with self.switch_to_popup_window(): with self.visible_selector('#id_image') as el: el.send_keys(os.path.join(self.TEST_IMG_DIR, 'img.png')) with self.clickable_selector('#upload-button') as el: el.click() with self.clickable_selector('#crop-button') as el: el.click() # Add required FK browser.find_element_by_xpath('//select[@id="id_author"]/option[@value=%d]' % author.pk).click() self.save_form() # Test that crops saved correctly article = Article.objects.all()[0] lead_sizes = list(Size.flatten(Article.LEAD_IMAGE_SIZES)) alt_sizes = list(Size.flatten(Article.ALT_IMAGE_SIZES)) self.assertTrue(article.lead_image.path.endswith('.jpg')) self.assertEqual(len(article.lead_image.related_object.thumbs.all()), len(lead_sizes)) self.assertTrue(article.alt_image.path.endswith('.png')) self.assertEqual(len(article.alt_image.related_object.thumbs.all()), len(alt_sizes))
def test_dont_generate_thumbs(self): article = Article.objects.create( title="Pudd'nhead Wilson", author=self.author, lead_image=self.create_unique_image('img.jpg')) article.lead_image.generate_thumbs() article = Article.objects.get(pk=article.pk) sizes = sorted(list(Size.flatten(Article.LEAD_IMAGE_SIZES)), key=lambda x: x.name) thumbs = sorted(list(article.lead_image.related_object.thumbs.all()), key=lambda x: x.name) self.assertEqual(len(thumbs), len(sizes)) for size, thumb in zip(sizes, thumbs): self.assertEqual(size.name, thumb.name) if size.width: self.assertEqual(size.width, thumb.width) if size.height: self.assertEqual(size.height, thumb.height) else: ratio = article.lead_image.height / article.lead_image.width self.assertAlmostEqual(thumb.height, ratio * size.width, delta=1) self.assertEqual(thumb.image.image, article.lead_image.related_object.image) self.assertFalse(default_storage.exists(thumb.image_name)) with self.assertRaises(IOError): default_storage.open(thumb.image_name, mode='rb')
def test_generate_thumbs(self): article = Article.objects.create(title="Pudd'nhead Wilson", author=self.author, lead_image=self.create_unique_image('img.jpg')) article.lead_image.generate_thumbs() article = Article.objects.get(pk=article.pk) sizes = sorted(list(Size.flatten(Article.LEAD_IMAGE_SIZES)), key=lambda x: x.name) thumbs = sorted(list(article.lead_image.related_object.thumbs.all()), key=lambda x: x.name) self.assertEqual(len(thumbs), len(sizes)) for size, thumb in zip(sizes, thumbs): self.assertEqual(size.name, thumb.name) if size.width: self.assertEqual(size.width, thumb.width) if size.height: self.assertEqual(size.height, thumb.height) else: ratio = article.lead_image.height / article.lead_image.width self.assertAlmostEqual(thumb.height, ratio * size.width, delta=1) self.assertEqual(thumb.image.image, article.lead_image.related_object.image) self.assertTrue(os.path.exists(thumb.path)) self.assertEqual((thumb.width, thumb.height), PIL.Image.open(thumb.path).size) image = PIL.Image.open(os.path.join(self.TEST_IMG_DIR, 'img.jpg')) image.thumbnail((50, 50)) image.save(os.path.join(self.TEST_IMG_DIR, 'new-img.jpg')) new_image_path = self.create_unique_image('new-img.jpg') article = Article.objects.create( title="Img Too Small", author=self.author, lead_image=new_image_path) self.assertRaises(CropDusterResizeException, article.lead_image.generate_thumbs)
class OrphanedThumbs(models.Model): TEST_SIZES = [ Size('main', w=600, h=480, auto=[ Size('main@2x', w=1200, h=960), ]), Size('secondary', w=600, h=480, auto=[ Size('secondary@2x', w=1200, h=960), ]) ] slug = models.SlugField() image = CropDusterField(upload_to="test", sizes=TEST_SIZES)
def test_prefetch_related_with_alt_images(self): img_map = {} for x in range(3): lead_image_path = self.create_unique_image('img.jpg') alt_image_path = self.create_unique_image('img.jpg') article = Article.objects.create(title="", author=self.author, lead_image=lead_image_path, alt_image=alt_image_path) article.lead_image.generate_thumbs() article.alt_image.generate_thumbs() img_map[article.pk] = (lead_image_path, alt_image_path) with self.assertNumQueries(5): articles = (Article.objects.filter( id__in=img_map.keys()).prefetch_related( 'lead_image__thumbs', 'alt_image__thumbs')) for article in articles: lead_name, alt_name = img_map[article.pk] self.assertEqual(lead_name, article.lead_image.related_object.image.name) self.assertEqual(alt_name, article.alt_image.related_object.image.name) lead_sizes = [ s.name for s in Size.flatten(Article.LEAD_IMAGE_SIZES) ] lead_thumbs = list( article.lead_image.related_object.thumbs.all()) self.assertEqual(len(lead_thumbs), len(lead_sizes)) for thumb in lead_thumbs: self.assertEqual(thumb.image_id, article.lead_image.related_object.pk) self.assertIn(thumb.name, lead_sizes) alt_sizes = [ s.name for s in Size.flatten(Article.ALT_IMAGE_SIZES) ] alt_thumbs = list( article.alt_image.related_object.thumbs.all()) self.assertEqual(len(alt_thumbs), len(alt_sizes)) for thumb in alt_thumbs: self.assertEqual(thumb.image_id, article.alt_image.related_object.pk) self.assertIn(thumb.name, alt_sizes)
def test_addform_single_image(self): self.load_admin(Author) browser = self.selenium browser.find_element_by_id('id_name').send_keys('Mark Twain') with self.clickable_selector( '#headshot-group .cropduster-button') as el: el.click() with self.switch_to_popup_window(): with self.visible_selector('#id_image') as el: el.send_keys(os.path.join(self.TEST_IMG_DIR, 'img.png')) with self.clickable_selector('#upload-button') as el: el.click() with self.clickable_selector('#crop-button') as el: el.click() self.save_form() author = Author.objects.all()[0] sizes = list(Size.flatten(Author.HEADSHOT_SIZES)) self.assertTrue(bool(author.headshot.name)) image = author.headshot.related_object thumbs = image.thumbs.all() self.assertEqual(len(thumbs), len(sizes)) main_thumb = image.thumbs.get(name='main') self.assertEqual( main_thumb.to_dict(), { 'reference_thumb_id': None, 'name': 'main', 'width': 220, 'height': 180, 'crop_w': 674, 'crop_h': 551, 'crop_x': 0, 'crop_y': 125, 'image_id': image.pk, 'id': main_thumb.pk, }) auto_thumb = image.thumbs.get(name='thumb') self.assertEqual( auto_thumb.to_dict(), { 'reference_thumb_id': main_thumb.pk, 'name': 'thumb', 'width': 110, 'height': 90, 'crop_w': None, 'crop_h': None, 'crop_x': None, 'crop_y': None, 'image_id': image.pk, 'id': auto_thumb.pk, }) self.assertTrue(default_storage.exists(auto_thumb.image_name))
def test_addform_single_image(self): self.load_admin(Author) browser = self.selenium browser.find_element_by_id('id_name').send_keys('Mark Twain') with self.clickable_selector('#headshot-group .cropduster-button') as el: el.click() with self.switch_to_popup_window(): with self.visible_selector('#id_image') as el: el.send_keys(os.path.join(self.TEST_IMG_DIR, 'img.jpg')) with self.clickable_selector('#upload-button') as el: el.click() with self.clickable_selector('#crop-button') as el: el.click() self.save_form() author = Author.objects.all()[0] sizes = list(Size.flatten(Author.HEADSHOT_SIZES)) self.assertTrue(bool(author.headshot.path)) image = author.headshot.related_object thumbs = image.thumbs.all() self.assertEqual(len(thumbs), len(sizes)) main_thumb = image.thumbs.get(name='main') self.assertEqual(main_thumb.to_dict(), { 'reference_thumb_id': None, 'name': 'main', 'width': 220, 'height': 180, 'crop_w': 674, 'crop_h': 551, 'crop_x': 0, 'crop_y': 125, 'image_id': image.pk, 'id': main_thumb.pk, }) auto_thumb = image.thumbs.get(name='thumb') self.assertEqual(auto_thumb.to_dict(), { 'reference_thumb_id': main_thumb.pk, 'name': 'thumb', 'width': 110, 'height': 90, 'crop_w': None, 'crop_h': None, 'crop_x': None, 'crop_y': None, 'image_id': image.pk, 'id': auto_thumb.pk, }) self.assertTrue(os.path.exists(auto_thumb.path))
class Article(models.Model): title = models.CharField(max_length=255) author = models.ForeignKey(to=Author, blank=True, null=True, on_delete=models.SET_NULL) LEAD_IMAGE_SIZES = [ Size(u'main', w=600, h=480, auto=[ Size(u'thumb', w=110, h=90), ]), Size(u'no_height', w=600), ] ALT_IMAGE_SIZES = [ Size(u'wide', w=600, h=300), ] lead_image = CropDusterField(upload_to="article/lead_image/%Y/%m", db_column='image', related_name="test_article_lead_image", sizes=LEAD_IMAGE_SIZES) alt_image = CropDusterField(upload_to="article/alt_image/%Y/%m", related_name="test_article_alt_image", sizes=ALT_IMAGE_SIZES, field_identifier="alt")
def test_generate_thumbs(self): article = Article.objects.create( title="Pudd'nhead Wilson", author=self.author, lead_image=self.create_unique_image('img.jpg')) article.lead_image.generate_thumbs() article = Article.objects.get(pk=article.pk) sizes = sorted(list(Size.flatten(Article.LEAD_IMAGE_SIZES)), key=lambda x: x.name) thumbs = sorted(list(article.lead_image.related_object.thumbs.all()), key=lambda x: x.name) self.assertEqual(len(thumbs), len(sizes)) for size, thumb in zip(sizes, thumbs): self.assertEqual(size.name, thumb.name) if size.width: self.assertEqual(size.width, thumb.width) if size.height: self.assertEqual(size.height, thumb.height) else: ratio = article.lead_image.height / article.lead_image.width self.assertAlmostEqual(thumb.height, ratio * size.width, delta=1) self.assertEqual(thumb.image.image, article.lead_image.related_object.image) self.assertTrue(default_storage.exists(thumb.image_name)) with default_storage.open(thumb.image_name, mode='rb') as f: self.assertEqual((thumb.width, thumb.height), PIL.Image.open(f).size) image = PIL.Image.open(os.path.join(self.TEST_IMG_DIR, 'img.jpg')) image.thumbnail((50, 50)) buf = BytesIO() image.save(buf, format=image.format) default_storage.save('new-img.jpg', buf) article = Article.objects.create(title="Img Too Small", author=self.author, lead_image='new-img.jpg') self.assertRaises(CropDusterResizeException, article.lead_image.generate_thumbs)
class MultipleFieldsInheritanceChild(MultipleFieldsInheritanceParent): image2 = CropDusterField(upload_to="test", sizes=[Size(u'main', w=600, h=480)], field_identifier="2")
class MultipleFieldsInheritanceParent(models.Model): slug = models.SlugField() image = CropDusterField(upload_to="test", sizes=[Size(u'main', w=600, h=480)])
def upload(request): if request.method == 'GET': return index(request) # The data we'll be returning as JSON data = { 'warning': [], } form = UploadForm(request.POST, request.FILES) if not form.is_valid(): errors = form['image'].errors or form.errors return json_error(request, 'upload', action="uploading file", errors=[force_text(errors)]) form_data = form.cleaned_data is_standalone = bool(form_data.get('standalone')) orig_file_path = form_data['image'].name if six.PY2 and isinstance(orig_file_path, six.text_type): orig_file_path = orig_file_path.encode('utf-8') orig_image = get_relative_media_url(orig_file_path) with default_storage.open(orig_image, mode='rb') as f: img = PIL.Image.open(BytesIO(f.read())) img.filename = f.name (w, h) = (orig_w, orig_h) = img.size if is_animated_gif(img) and not has_animated_gif_support(): data['warning'].append( u"This server does not have animated gif support; your uploaded image " u"has been made static.") tmp_image = Image(image=orig_image) preview_w = form_data.get('preview_width') or PREVIEW_WIDTH preview_h = form_data.get('preview_height') or PREVIEW_HEIGHT # First pass resize if it's too large resize_ratio = min(preview_w / w, preview_h / h) def fit_preview(im): (w, h) = im.size if resize_ratio < 1: w = int(round(w * resize_ratio)) h = int(round(h * resize_ratio)) preview_img = im.resize((w, h), PIL.Image.ANTIALIAS) else: preview_img = im return preview_img if not is_standalone: preview_file_path = tmp_image.get_image_path('_preview') process_image(img, preview_file_path, fit_preview) data.update({ 'crop': { 'orig_image': orig_image, 'orig_w': orig_w, 'orig_h': orig_h, 'image_id': None, }, 'url': tmp_image.get_image_url('_preview'), 'orig_image': orig_image, 'orig_w': orig_w, 'orig_h': orig_h, 'width': w, 'height': h, }) if not is_standalone: return HttpResponse(json.dumps(data), content_type='application/json') size = Size('crop', w=img.size[0], h=img.size[1]) md5 = form_data.get('md5') try: standalone_image = StandaloneImage.objects.get(md5=md5) except StandaloneImage.DoesNotExist: standalone_image = StandaloneImage(md5=md5, image=orig_image) standalone_image.save() cropduster_image, created = Image.objects.get_or_create( content_type=ContentType.objects.get_for_model(StandaloneImage), object_id=standalone_image.pk) if not cropduster_image.image: cropduster_image.image = orig_image cropduster_image.save() elif cropduster_image.image.name != orig_image: data['crop']['orig_image'] = data[ 'orig_image'] = cropduster_image.image.name data['url'] = cropduster_image.get_image_url('_preview') with cropduster_image.image as f: f.open() img = PIL.Image.open(BytesIO(f.read())) img.filename = f.name preview_file_path = cropduster_image.get_image_path('_preview') if not default_storage.exists(preview_file_path): process_image(img, preview_file_path, fit_preview) thumb = cropduster_image.save_size(size, standalone=True, commit=False) sizes = form_data.get('sizes') or [] if len(sizes) == 1: size = sizes[0] else: size = Size('crop') data.update({ 'thumbs': [{ 'crop_x': thumb.crop_x, 'crop_y': thumb.crop_y, 'crop_w': thumb.crop_w, 'crop_h': thumb.crop_h, 'width': thumb.width, 'height': thumb.height, 'id': None, 'changed': True, 'size': json.dumps(size), 'name': thumb.name, }] }) data['crop'].update({ 'image_id': cropduster_image.pk, 'sizes': json.dumps([size]), }) return HttpResponse(json.dumps(data), content_type='application/json')
def upload(request): size_set = SizeSet.objects.get(id=request.GET["size_set"]) # Get the current aspect ratio if "aspect_ratio_id" in request.POST: aspect_ratio_id = int(request.POST["aspect_ratio_id"]) else: aspect_ratio_id = 0 image_id = None if "image_id" in request.GET: image_id = request.GET["image_id"] elif "image_id" in request.POST: image_id = request.POST["image_id"] try: image_id = int(image_id) image = CropDusterImage.objects.get(id=image_id) except: image = CropDusterImage(size_set=size_set) size = Size.objects.get_size_by_ratio(size_set.id, aspect_ratio_id) or Size() # Get the current crop try: crop = Crop.objects.get(image=image.id, size=size.id) except Crop.DoesNotExist: crop = Crop() crop.crop_w = size.width crop.crop_h = size.height crop.crop_x = 0 crop.crop_y = 0 crop.image = image crop.size = size if request.method == "POST": if request.FILES: # Process uploaded image form formset = ImageForm(request.POST, request.FILES, instance=image) if formset.is_valid(): if CROPDUSTER_EXIF_DATA: # Check for exif data and use it to populate caption/attribution try: exif_data = process_file( io.BytesIO( b"%s" % formset.cleaned_data["image"].file.getvalue())) except AttributeError: exif_data = {} if not formset.cleaned_data[ "caption"] and "Image ImageDescription" in exif_data: formset.data["caption"] = exif_data[ "Image ImageDescription"].__str__() if not formset.cleaned_data[ "attribution"] and "EXIF UserComment" in exif_data: formset.data["attribution"] = exif_data[ "EXIF UserComment"].__str__() image = formset.save() crop.image = image crop_formset = CropForm(instance=crop) else: # Invalid upload return form errors = formset.errors.values()[0] context = { "aspect_ratio_id": 0, "errors": errors, "formset": formset, "image_element_id": request.GET["image_element_id"], "static_url": settings.STATIC_URL, } context = RequestContext(request, context) return render_to_response("admin/upload.html", context) else: #If its the first frame, get the image formset and save it (for attribution) if not aspect_ratio_id: formset = ImageForm(request.POST, instance=image) if formset.is_valid(): formset.save() else: formset = ImageForm(instance=image) # If there's no cropping to be done, then just complete the process if size.id: # Lets save the crop request.POST['size'] = size.id request.POST['image'] = image.id crop_formset = CropForm(request.POST, instance=crop) if crop_formset.is_valid(): crop = crop_formset.save() #Now get the next crop if it exists aspect_ratio_id = aspect_ratio_id + 1 size = Size.objects.get_size_by_ratio( size_set, aspect_ratio_id) # If there's another crop if size: try: crop = Crop.objects.get(image=image.id, size=size.id) crop_formset = CropForm(instance=crop) except Crop.DoesNotExist: crop = Crop() crop.crop_w = size.width crop.crop_h = size.height crop.crop_x = 0 crop.crop_y = 0 crop.size = size crop_formset = CropForm() # Nothing being posted, get the image and form if they exist else: formset = ImageForm(instance=image) crop_formset = CropForm(instance=crop) # If theres more cropping to be done or its the first frame, # show the upload/crop form if (size and size.id) or request.method != "POST": crop_w = crop.crop_w or size.width crop_h = crop.crop_h or size.height # Combine errors from both forms, eliminate duplicates errors = dict(crop_formset.errors) errors.update(formset.errors) all_errors = [] for error in errors.items(): if error[0] != '__all__': string = u"%s: %s" % (error[0].capitalize(), error[1].as_text()) else: string = error[1].as_text() all_errors.append(string) context = { "aspect_ratio": size.aspect_ratio, "aspect_ratio_id": aspect_ratio_id, "browser_width": BROWSER_WIDTH, "crop_formset": crop_formset, "crop_w": crop_w, "crop_h": crop_h, "crop_x": crop.crop_x or 0, "crop_y": crop.crop_y or 0, "errors": all_errors, "formset": formset, "image": image, "image_element_id": request.GET["image_element_id"], "image_exists": image.image and os.path.exists(image.image.path), "min_w": size.width, "min_h": size.height, "static_url": settings.STATIC_URL, } context = RequestContext(request, context) return render_to_response("admin/upload.html", context) # No more cropping to be done, close out else: image_thumbs = [ image.thumbnail_url(size.slug) for size in image.size_set.get_unique_ratios() ] context = { "image": image, "image_thumbs": image_thumbs, "image_element_id": request.GET["image_element_id"], "static_url": settings.STATIC_URL, } context = RequestContext(request, context) return render_to_response("admin/complete.html", context)