def test_filtering_tags(self): get_image_model().objects.get(id=6).tags.add('test') response = self.get_response(tags='test') content = json.loads(response.content.decode('UTF-8')) image_id_list = self.get_image_id_list(content) self.assertEqual(image_id_list, [6])
def image(request, pk, specs): ''' Request an image given some specs and redirects to it ''' image = get_object_or_404(get_image_model(), pk=pk) rendition = get_rendition_or_not_found(image, specs) return redirect(rendition.url)
def get_field_display_value(self, field_name, field=None): """ Return a display value for a field """ # First we check for a 'get_fieldname_display' property/method on # the model, and return the value of that, if present. val_funct = getattr(self.instance, 'get_%s_display' % field_name, None) if val_funct is not None: if callable(val_funct): return val_funct() return val_funct # If we have a real field, we can utilise that to try to display # something more useful if field is not None: try: field_type = field.get_internal_type() if (field_type == 'ForeignKey' and field.related_model == get_image_model()): # The field is an image return self.get_image_field_display(field_name, field) if (field_type == 'ForeignKey' and field.related_model == get_document_model()): # The field is a document return self.get_document_field_display(field_name, field) except AttributeError: pass # Resort to getting the value of 'field_name' from the instance return getattr(self.instance, field_name, self.model_admin.get_empty_value_display(field_name))
def test_dots_in_title(self): image = get_image_model().objects.create( title="a.b.c", file=get_test_image_file() ) self.assertSlugEqual(image.slug, 'ab')
def generate_url(request, image_id, filter_spec): # Get the image Image = get_image_model() try: image = Image.objects.get(id=image_id) except Image.DoesNotExist: return JsonResponse({"error": "Cannot find image."}, status=404) # Check if this user has edit permission on this image if not permission_policy.user_has_permission_for_instance(request.user, "change", image): return JsonResponse({"error": "You do not have permission to generate a URL for this image."}, status=403) # Parse the filter spec to make sure its valid try: Filter(spec=filter_spec).operations except InvalidFilterSpecError: return JsonResponse({"error": "Invalid filter spec."}, status=400) # Generate url signature = generate_signature(image_id, filter_spec) url = reverse("wagtailimages_serve", args=(signature, image_id, filter_spec)) # Get site root url try: site_root_url = Site.objects.get(is_default_site=True).root_url except Site.DoesNotExist: site_root_url = Site.objects.first().root_url # Generate preview url preview_url = reverse("wagtailimages:preview", args=(image_id, filter_spec)) return JsonResponse({"url": site_root_url + url, "preview_url": preview_url}, status=200)
def test_image_file_deleted_oncommit(self): with transaction.atomic(): image = get_image_model().objects.create(title="Test Image", file=get_test_image_file()) self.assertTrue(image.file.storage.exists(image.file.name)) image.delete() self.assertTrue(image.file.storage.exists(image.file.name)) self.assertFalse(image.file.storage.exists(image.file.name))
def test_limit_max_none_gives_no_errors(self): response = self.get_response(limit=1000000) content = json.loads(response.content.decode('UTF-8')) self.assertEqual(response.status_code, 200) self.assertEqual(len(content['items']), get_image_model().objects.count())
def register_signal_handlers(): Image = get_image_model() Rendition = Image.get_rendition_model() pre_save.connect(pre_save_image_feature_detection, sender=Image) post_delete.connect(post_delete_file_cleanup, sender=Image) post_delete.connect(post_delete_file_cleanup, sender=Rendition)
def handle(self, *args, **options): base_url = options['base_url'] dest_dir = options['dest_dir'] for subdir in ('images', 'original_images'): directory = os.path.join(dest_dir, subdir) if not os.path.exists(directory): os.makedirs(directory) images = get_image_model().objects.all() image_count = images.count() for i, image in enumerate(images): image_prefix = '%d/%d (%d) ' % (i + 1, image_count, image.pk) self.stdout.write(image_prefix, ending='') self.save(base_url, dest_dir, image.file.name) renditions = image.renditions.all() rendition_count = renditions.count() for j, rendition in enumerate(renditions): rendition_prefix = '%d/%d (%d) ' % (j + 1, rendition_count, rendition.pk) self.stdout.write(image_prefix + rendition_prefix, ending='') self.save(base_url, dest_dir, rendition.file.name)
def test_very_long_title(self): image = get_image_model().objects.create( title="a" * 255, file=get_test_image_file() ) self.assertSlugEqual(image.slug, ('a' * 50))
def test_offset_total_count(self): response = self.get_response(offset=10) content = json.loads(response.content.decode('UTF-8')) # The total count must not be affected by "offset" self.assertEqual(content['meta']['total_count'], get_image_model().objects.count())
def test_basic(self): response = self.get_response() self.assertEqual(response.status_code, 200) self.assertEqual(response['Content-type'], 'application/json') # Will crash if the JSON is invalid content = json.loads(response.content.decode('UTF-8')) # Check that the meta section is there self.assertIn('meta', content) self.assertIsInstance(content['meta'], dict) # Check that the total count is there and correct self.assertIn('total_count', content['meta']) self.assertIsInstance(content['meta']['total_count'], int) self.assertEqual(content['meta']['total_count'], get_image_model().objects.count()) # Check that the items section is there self.assertIn('items', content) self.assertIsInstance(content['items'], list) # Check that each image has a meta section with type and detail_url attributes for image in content['items']: self.assertIn('meta', image) self.assertIsInstance(image['meta'], dict) self.assertEqual(set(image['meta'].keys()), {'type', 'detail_url', 'tags'}) # Type should always be wagtailimages.Image self.assertEqual(image['meta']['type'], 'wagtailimages.Image') # Check detail url self.assertEqual(image['meta']['detail_url'], 'http://localhost/api/v2beta/images/%d/' % image['id'])
def test_image_signal_handlers(self): image = get_image_model().objects.create(title="Test Image", file=get_test_image_file()) image_path = image.file.path image.delete() self.assertFalse(os.path.exists(image_path))
def delete(request, image_id): image = get_object_or_404(get_image_model(), id=image_id) if not permission_policy.user_has_permission_for_instance( request.user, 'delete', image): return permission_denied(request) if image.folder: parent_folder = image.folder else: parent_folder = False if request.method == 'POST': image.delete() messages.success(request, _("Image '{0}' deleted.").format(image.title)) response = redirect('wagtailimages:index') if parent_folder: response['Location'] += '?folder={0}'.format(parent_folder.id) return response return render(request, "wagtailimages/images/confirm_delete.html", { 'image': image, })
def Image(props): """ Inspired by: - https://github.com/torchbox/wagtail/blob/master/wagtail/wagtailimages/rich_text.py - https://github.com/torchbox/wagtail/blob/master/wagtail/wagtailimages/shortcuts.py - https://github.com/torchbox/wagtail/blob/master/wagtail/wagtailimages/formats.py """ image_model = get_image_model() alignment = props.get('alignment', 'left') alt_text = props.get('altText', '') try: image = image_model.objects.get(id=props['id']) except image_model.DoesNotExist: return DOM.create_element('img', {'alt': alt_text}) image_format = get_image_format(alignment) rendition = get_rendition_or_not_found(image, image_format.filter_spec) return DOM.create_element( 'img', dict( rendition.attrs_dict, **{ 'class': image_format.classnames, 'src': rendition.url, 'alt': alt_text, }))
def image_chosen(request, image_id): image = get_object_or_404(get_image_model(), id=image_id) return render_modal_workflow( request, None, 'wagtailimages/chooser/image_chosen.js', {'image_json': get_image_json(image)} )
def add(request): ImageModel = get_image_model() ImageForm = get_image_form(ImageModel) if request.method == 'POST': image = ImageModel(uploaded_by_user=request.user) form = ImageForm(request.POST, request.FILES, instance=image, user=request.user) if form.is_valid(): # Set image file size image.file_size = image.file.size form.save() # Reindex the image to make sure all tags are indexed search_index.insert_or_update_object(image) messages.success(request, _("Image '{0}' added.").format(image.title), buttons=[ messages.button(reverse('wagtailimages:edit', args=(image.id,)), _('Edit')) ]) return redirect('wagtailimages:index') else: messages.error(request, _("The image could not be created due to errors.")) else: form = ImageForm(user=request.user) return render(request, "wagtailimages/images/add.html", { 'form': form, })
def create_thumbnail(model_instance): # CREATING IMAGE FROM THUMBNAIL backend = detect_backend(model_instance.url) thumbnail_url = backend.get_thumbnail_url() if backend.__class__.__name__ == 'YoutubeBackend': if thumbnail_url.endswith('hqdefault.jpg'): for resolution in YOUTUBE_RESOLUTIONS: temp_thumbnail_url = thumbnail_url.replace( 'hqdefault.jpg', resolution) if checkUrl(temp_thumbnail_url): thumbnail_url = temp_thumbnail_url break img_temp = NamedTemporaryFile() try: img_temp.write(urllib2.urlopen(thumbnail_url).read()) except: http = urllib3.PoolManager() img_temp.write(http.request('GET', thumbnail_url).data) img_temp.flush() image = get_image_model()(title=model_instance.title) image.file.save(model_instance.title + '.jpg', File(img_temp)) model_instance.thumbnail = image model_instance.thumbnail.tags.add('video-thumbnail') model_instance.save()
def get_image_model(): warnings.warn( "wagtail.wagtailimages.models.get_image_model " "has been moved to wagtail.wagtailimages.get_image_model", RemovedInWagtail110Warning) from wagtail.wagtailimages import get_image_model return get_image_model()
def chooser(request): Image = get_image_model() if permission_policy.user_has_permission(request.user, 'add'): ImageForm = get_image_form(Image) uploadform = ImageForm(user=request.user) else: uploadform = None images = Image.objects.order_by('-created_at') # allow hooks to modify the queryset for hook in hooks.get_hooks('construct_image_chooser_queryset'): images = hook(images, request) if ('q' in request.GET or 'p' in request.GET or 'tag' in request.GET or 'collection_id' in request.GET): # this request is triggered from search, pagination or 'popular tags'; # we will just render the results.html fragment collection_id = request.GET.get('collection_id') if collection_id: images = images.filter(collection=collection_id) searchform = SearchForm(request.GET) if searchform.is_valid(): q = searchform.cleaned_data['q'] images = images.search(q) is_searching = True else: is_searching = False q = None tag_name = request.GET.get('tag') if tag_name: images = images.filter(tags__name=tag_name) # Pagination paginator, images = paginate(request, images, per_page=12) return render( request, "wagtailimages/chooser/results.html", { 'images': images, 'is_searching': is_searching, 'query_string': q, 'will_select_format': request.GET.get('select_format') }) else: paginator, images = paginate(request, images, per_page=12) context = get_chooser_context(request) context.update({ 'images': images, 'uploadform': uploadform, }) return render_modal_workflow(request, 'wagtailimages/chooser/chooser.html', 'wagtailimages/chooser/chooser.js', context)
def get_images(self, request): tags = self.tags.all() # Be compatible with swappable image model model = get_image_model() # Creating empty Queryset from Wagtail image model return model.objects.filter(tags__in=tags).distinct()
def test_deprecated_get_image_model(self): from wagtail.wagtailimages.models import get_image_model with warnings.catch_warnings(record=True) as ws: warnings.simplefilter('always') self.assertIs(Image, get_image_model()) self.assertEqual(len(ws), 1) self.assertIs(ws[0].category, RemovedInWagtail110Warning)
def test_rendition_file_deleted_oncommit(self): with transaction.atomic(): image = get_image_model().objects.create(title="Test Image", file=get_test_image_file()) rendition = image.get_rendition('original') self.assertTrue(rendition.file.storage.exists(rendition.file.name)) rendition.delete() self.assertTrue(rendition.file.storage.exists(rendition.file.name)) self.assertFalse(rendition.file.storage.exists(rendition.file.name))
def multichooser_select(request): ids = json.loads(request.GET.get('ids')) images = [get_object_or_404(get_image_model(), id=id_) for id_ in ids] return render_modal_workflow(request, None, 'wagtailimages/chooser/image_chosen.js', {'image_json': get_images_json(images)})
def test_image_file_deleted_oncommit(self): with transaction.atomic(): image = get_image_model().objects.create( title="Test Image", file=get_test_image_file()) self.assertTrue(image.file.storage.exists(image.file.name)) image.delete() self.assertTrue(image.file.storage.exists(image.file.name)) self.assertFalse(image.file.storage.exists(image.file.name))
def url_generator(request, image_id): image = get_object_or_404(get_image_model(), id=image_id) if not permission_policy.user_has_permission_for_instance(request.user, "change", image): return permission_denied(request) form = URLGeneratorForm(initial={"filter_method": "original", "width": image.width, "height": image.height}) return render(request, "wagtailimages/images/url_generator.html", {"image": image, "form": form})
def index(request): Image = get_image_model() # Get images (filtered by user permission) images = permission_policy.instances_user_has_any_permission_for(request.user, ["change", "delete"]).order_by( "-created_at" ) # Search query_string = None if "q" in request.GET: form = SearchForm(request.GET, placeholder=_("Search images")) if form.is_valid(): query_string = form.cleaned_data["q"] images = images.search(query_string) else: form = SearchForm(placeholder=_("Search images")) # Filter by collection current_collection = None collection_id = request.GET.get("collection_id") if collection_id: try: current_collection = Collection.objects.get(id=collection_id) images = images.filter(collection=current_collection) except (ValueError, Collection.DoesNotExist): pass paginator, images = paginate(request, images) collections = permission_policy.collections_user_has_any_permission_for(request.user, ["add", "change"]) if len(collections) < 2: collections = None # Create response if request.is_ajax(): return render( request, "wagtailimages/images/results.html", {"images": images, "query_string": query_string, "is_searching": bool(query_string)}, ) else: return render( request, "wagtailimages/images/index.html", { "images": images, "query_string": query_string, "is_searching": bool(query_string), "search_form": form, "popular_tags": popular_tags_for_model(Image), "collections": collections, "current_collection": current_collection, "user_can_add": permission_policy.user_has_permission(request.user, "add"), }, )
def show_tagged_figures(request, tag_id_in_str): tag_id = int(tag_id_in_str) tag = get_object_or_404(Tag, pk=tag_id) Image = get_image_model() figures = Image.objects.filter(tags__id=tag_id) return render( request, 'tags/tagged_figures.html', { 'tag': tag, 'figures': figures, }) # yapf: disable
def usage(request, image_id): image = get_object_or_404(get_image_model(), id=image_id) paginator, used_by = paginate(request, image.get_usage()) return render(request, "wagtailimages/images/usage.html", { 'image': image, 'used_by': used_by })
def test_rendition_file_deleted_oncommit(self): with transaction.atomic(): image = get_image_model().objects.create( title="Test Image", file=get_test_image_file()) rendition = image.get_rendition('original') self.assertTrue(rendition.file.storage.exists(rendition.file.name)) rendition.delete() self.assertTrue(rendition.file.storage.exists(rendition.file.name)) self.assertFalse(rendition.file.storage.exists(rendition.file.name))
def test_s3_files_use_secure_urls(self): image_file = get_test_image_file(filename='test.png') Image = get_image_model() image = Image(file=image_file) self.assertEqual( image.file.url, 'https://s3.amazonaws.com/test_s3_bucket/root/test.png')
def index(request): Image = get_image_model() # Get images (filtered by user permission) images = permission_policy.instances_user_has_any_permission_for( request.user, ['change', 'delete'] ).order_by('-created_at') # Search query_string = None if 'q' in request.GET: form = SearchForm(request.GET, placeholder=_("Search images")) if form.is_valid(): query_string = form.cleaned_data['q'] images = images.search(query_string) else: form = SearchForm(placeholder=_("Search images")) # Filter by collection current_collection = None collection_id = request.GET.get('collection_id') if collection_id: try: current_collection = Collection.objects.get(id=collection_id) images = images.filter(collection=current_collection) except (ValueError, Collection.DoesNotExist): pass paginator, images = paginate(request, images) collections = permission_policy.collections_user_has_any_permission_for( request.user, ['add', 'change'] ) if len(collections) < 2: collections = None # Create response if request.is_ajax(): return render(request, 'wagtailimages/images/results.html', { 'images': images, 'query_string': query_string, 'is_searching': bool(query_string), }) else: return render(request, 'wagtailimages/images/index.html', { 'images': images, 'query_string': query_string, 'is_searching': bool(query_string), 'search_form': form, 'popular_tags': popular_tags_for_model(Image), 'collections': collections, 'current_collection': current_collection, 'user_can_add': permission_policy.user_has_permission(request.user, 'add'), })
def preview(request, image_id, filter_spec): image = get_object_or_404(get_image_model(), id=image_id) try: response = HttpResponse() image = Filter(spec=filter_spec).run(image, response) response['Content-Type'] = 'image/' + image.format_name return response except InvalidFilterSpecError: return HttpResponse("Invalid filter spec: " + filter_spec, content_type='text/plain', status=400)
def test_tags(self): image = get_image_model().objects.get(id=5) image.tags.add('hello') image.tags.add('world') response = self.get_response(5) content = json.loads(response.content.decode('UTF-8')) self.assertIn('tags', content['meta']) self.assertEqual(content['meta']['tags'], ['hello', 'world'])
def test_update(self): image = get_image_model().objects.create( title="Test image", file=get_test_image_file() ) image.title = 'Something else' image.save() self.assertSlugEqual(image.slug, 'something-else')
def test_s3_files_use_secure_urls(self): image_file = get_test_image_file(filename='test.png') Image = get_image_model() image = Image(file=image_file) self.assertEqual( image.file.url, 'https://s3.amazonaws.com/test_s3_bucket/root/test.png' )
def setUpTestData(cls): image_model = get_image_model() cls.test_image_1 = image_model.objects.create( title="Test image 1", file=get_test_image_file(), ) cls.test_image_2 = image_model.objects.create( title="Test image 2", file=get_test_image_file(), )
def test_image_file_deleted(self): ''' this test duplicates `test_image_file_deleted_oncommit` for django 1.8 support and can be removed once django 1.8 is no longer supported ''' with transaction.atomic(): image = get_image_model().objects.create(title="Test Image", file=get_test_image_file()) self.assertTrue(image.file.storage.exists(image.file.name)) image.delete() self.assertFalse(image.file.storage.exists(image.file.name))
def test_custom_image_signal_handlers(self): #: Sadly signal receivers only get connected when starting django. #: We will re-attach them here to mimic the django startup behavior #: and get the signals connected to our custom model.. signal_handlers.register_signal_handlers() image = get_image_model().objects.create(title="Test CustomImage", file=get_test_image_file()) image_path = image.file.path image.delete() self.assertFalse(os.path.exists(image_path))
def test_update(self): image = get_image_model().objects.create( title="Test image", file=get_test_image_file() ) image.save() self.assertEqual(image.version, 2) image.save() self.assertEqual(image.version, 3)
def delete(request, image_id): image = get_object_or_404(get_image_model(), id=image_id) if not permission_policy.user_has_permission_for_instance(request.user, "delete", image): return permission_denied(request) if request.method == "POST": image.delete() messages.success(request, _("Image '{0}' deleted.").format(image.title)) return redirect("wagtailimages:index") return render(request, "wagtailimages/images/confirm_delete.html", {"image": image})
def unregister_signal_handlers(): Image = get_image_model() Document = get_document_model() for model in get_page_models(): page_published.disconnect(purge_page_from_cache, sender=model) page_unpublished.disconnect(purge_page_from_cache, sender=model) post_save.disconnect(purge_image_from_cache, sender=Image) post_delete.disconnect(purge_image_from_cache, sender=Image) post_save.disconnect(purge_document_from_cache, sender=Document) post_delete.disconnect(purge_document_from_cache, sender=Document)
def describe_collection_docs(collection): images_count = get_image_model().objects.filter(collection=collection).count() if images_count: url = urlresolvers.reverse('wagtailimages:index') + ('?collection_id=%d' % collection.id) return { 'count': images_count, 'count_text': ungettext( "%(count)s image", "%(count)s images", images_count ) % {'count': images_count}, 'url': url, }
def delete(request, image_id): image = get_object_or_404(get_image_model(), id=image_id) if not request.is_ajax(): return HttpResponseBadRequest("Cannot POST to this view without AJAX") if not permission_policy.user_has_permission_for_instance(request.user, 'delete', image): raise PermissionDenied image.delete() return JsonResponse({ 'success': True, 'image_id': int(image_id), })
def url_generator(request, image_id): image = get_object_or_404(get_image_model(), id=image_id) if not permission_policy.user_has_permission_for_instance(request.user, 'change', image): return permission_denied(request) form = URLGeneratorForm(initial={ 'filter_method': 'original', 'width': image.width, 'height': image.height, }) return render(request, "wagtailimages/images/url_generator.html", { 'image': image, 'form': form, })
def expand_db_attributes(attrs, for_editor): """ Given a dict of attributes from the <embed> tag, return the real HTML representation. """ Image = get_image_model() try: image = Image.objects.get(id=attrs['id']) except Image.DoesNotExist: return "<img>" image_format = get_image_format(attrs['format']) if for_editor: return image_format.image_to_editor_html(image, attrs['alt']) else: return image_format.image_to_html(image, attrs['alt'])
def test_thumbnail(self): # Add a new image with source file image = get_image_model().objects.create( title="Test image", file=get_test_image_file(), ) response = self.get_response(image.id) content = json.loads(response.content.decode('UTF-8')) self.assertIn('thumbnail', content) self.assertEqual(content['thumbnail']['width'], 165) self.assertEqual(content['thumbnail']['height'], 123) self.assertTrue(content['thumbnail']['url'].startswith('/media/images/test')) # Check that source_image_error didn't appear self.assertNotIn('source_image_error', content['meta'])
def add_image(self, filename): filename_only = os.path.split(filename)[-1] with open(filename, 'rb') as f: image_file = SimpleUploadedFile(filename_only, f.read()) response = self.client.post(reverse('wagtailimages:add'), { 'title': filename_only, 'file': image_file, }) if 302 != response.status_code: raise RuntimeError('something went wrong: {}'.format(response)) image_model = get_image_model() image = image_model.objects.filter(title=filename_only).latest('pk') self.stdout.write('added image {}: {}'.format(image.pk, image))
def delete(self, *args, **kwargs): # Recursively delete the sub folders for sub_folder in self.get_subfolders(): sub_folder.delete() # Delete the images Image = get_image_model() images = Image.objects.filter(folder=self) for image in images: image.delete() try: # Delete the physical folder shutil.rmtree(self.get_complete_path()) except FileNotFoundError: pass super(ImageFolder, self).delete()
def test_thumbnail(self): # Add a new image with source file image = get_image_model().objects.create( title="Test image", file=get_test_image_file(), ) response = self.get_response(image.id) content = json.loads(response.content.decode('UTF-8')) self.assertIn('thumbnail', content) self.assertEqual(content['thumbnail'], { 'url': '/media/images/test.max-165x165.png', 'width': 165, 'height': 123 }) # Check that source_image_error didn't appear self.assertNotIn('source_image_error', content['meta'])