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 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 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 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, "tuiuiuimages/images/usage.html", { 'image': image, 'used_by': used_by })
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 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_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 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 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 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 chooser_select_format(request, image_id): image = get_object_or_404(get_image_model(), id=image_id) if request.method == 'POST': form = ImageInsertionForm(request.POST, initial={'alt_text': image.default_alt_text}) if form.is_valid(): format = get_image_format(form.cleaned_data['format']) preview_image = image.get_rendition(format.filter_spec) image_json = json.dumps({ 'id': image.id, 'title': image.title, 'format': format.name, 'alt': form.cleaned_data['alt_text'], 'class': format.classnames, 'edit_link': reverse('tuiuiuimages:edit', args=(image.id, )), 'preview': { 'url': preview_image.url, 'width': preview_image.width, 'height': preview_image.height, }, 'html': format.image_to_editor_html(image, form.cleaned_data['alt_text']), }) return render_modal_workflow( request, None, 'tuiuiuimages/chooser/image_chosen.js', {'image_json': image_json}) else: initial = {'alt_text': image.default_alt_text} initial.update(request.GET.dict()) form = ImageInsertionForm(initial=initial) return render_modal_workflow(request, 'tuiuiuimages/chooser/select_format.html', 'tuiuiuimages/chooser/select_format.js', { 'image': image, 'form': form })
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('tuiuiuimages:index') return render(request, "tuiuiuimages/images/confirm_delete.html", { 'image': image, })
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 chooser_upload(request): Image = get_image_model() ImageForm = get_image_form(Image) searchform = SearchForm() if request.method == 'POST': image = Image(uploaded_by_user=request.user) form = ImageForm(request.POST, request.FILES, instance=image, user=request.user) if form.is_valid(): form.save() # Reindex the image to make sure all tags are indexed search_index.insert_or_update_object(image) if request.GET.get('select_format'): form = ImageInsertionForm( initial={'alt_text': image.default_alt_text}) return render_modal_workflow( request, 'tuiuiuimages/chooser/select_format.html', 'tuiuiuimages/chooser/select_format.js', { 'image': image, 'form': form }) else: # not specifying a format; return the image details now return render_modal_workflow( request, None, 'tuiuiuimages/chooser/image_chosen.js', {'image_json': get_image_json(image)}) else: form = ImageForm(user=request.user) images = Image.objects.order_by('-created_at') paginator, images = paginate(request, images, per_page=12) return render_modal_workflow(request, 'tuiuiuimages/chooser/chooser.html', 'tuiuiuimages/chooser/chooser.js', { 'images': images, 'uploadform': form, 'searchform': searchform })
class ServeView(View): model = get_image_model() action = 'serve' key = None @classonlymethod def as_view(cls, **initkwargs): if 'action' in initkwargs: if initkwargs['action'] not in ['serve', 'redirect']: raise ImproperlyConfigured( "ServeView action must be either 'serve' or 'redirect'") return super(ServeView, cls).as_view(**initkwargs) def get(self, request, signature, image_id, filter_spec): if not verify_signature( signature.encode(), image_id, filter_spec, key=self.key): raise PermissionDenied image = get_object_or_404(self.model, id=image_id) # Get/generate the rendition try: rendition = image.get_rendition(filter_spec) except SourceImageIOError: return HttpResponse("Source image file not found", content_type='text/plain', status=410) except InvalidFilterSpecError: return HttpResponse("Invalid filter spec: " + filter_spec, content_type='text/plain', status=400) return getattr(self, self.action)(rendition) def serve(self, rendition): # Open and serve the file rendition.file.open('rb') image_format = imghdr.what(rendition.file) return StreamingHttpResponse(FileWrapper(rendition.file), content_type='image/' + image_format) def redirect(self, rendition): # Redirect to the file's public location return HttpResponsePermanentRedirect(rendition.url)
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 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, "tuiuiuimages/images/url_generator.html", { 'image': image, 'form': form, })
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('tuiuiuimages_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('tuiuiuimages:preview', args=(image_id, filter_spec)) return JsonResponse( { 'url': site_root_url + url, 'preview_url': preview_url }, status=200)
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 tuiuiuimages.Image self.assertEqual(image['meta']['type'], 'tuiuiuimages.Image') # Check detail url self.assertEqual( image['meta']['detail_url'], 'http://localhost/api/v2beta/images/%d/' % image['id'])
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('tuiuiuimages:edit', args=(image.id, )), _('Edit')) ]) return redirect('tuiuiuimages:index') else: messages.error(request, _("The image could not be created due to errors.")) else: form = ImageForm(user=request.user) return render(request, "tuiuiuimages/images/add.html", { 'form': form, })
def edit(request, image_id, callback=None): Image = get_image_model() ImageForm = get_image_edit_form(Image) image = get_object_or_404(Image, 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, 'change', image): raise PermissionDenied form = ImageForm( request.POST, request.FILES, instance=image, prefix='image-' + image_id, user=request.user ) if form.is_valid(): form.save() # Reindex the image to make sure all tags are indexed for backend in get_search_backends(): backend.add(image) return JsonResponse({ 'success': True, 'image_id': int(image_id), }) else: return JsonResponse({ 'success': False, 'image_id': int(image_id), 'form': render_to_string('tuiuiuimages/multiple/edit_form.html', { 'image': image, 'form': form, }, request=request), })
def test_invalid_get_image_model(self): """Test get_image_model with an invalid model string""" with self.assertRaises(ImproperlyConfigured): get_image_model()
class ImagesAPIEndpoint(BaseAPIEndpoint): base_serializer_class = ImageSerializer filter_backends = [FieldsFilter, OrderingFilter, SearchFilter] extra_api_fields = ['title', 'tags', 'width', 'height'] name = 'images' model = get_image_model()
def test_standard_get_image_model(self): """Test get_image_model with no TUIUIUIMAGES_IMAGE_MODEL""" del settings.TUIUIUIMAGES_IMAGE_MODEL from tuiuiu.tuiuiuimages.models import Image self.assertIs(get_image_model(), Image)
def test_unknown_get_image_model(self): """Test get_image_model with an unknown model""" with self.assertRaises(ImproperlyConfigured): get_image_model()
def test_custom_get_image_model(self): """Test get_image_model with a custom image model""" self.assertIs(get_image_model(), CustomImage)
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) q = None 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 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, "tuiuiuimages/chooser/results.html", { 'images': images, 'is_searching': is_searching, 'query_string': q, 'will_select_format': request.GET.get('select_format') }) else: searchform = SearchForm() collections = Collection.objects.all() if len(collections) < 2: collections = None paginator, images = paginate(request, images, per_page=12) return render_modal_workflow( request, 'tuiuiuimages/chooser/chooser.html', 'tuiuiuimages/chooser/chooser.js', { 'images': images, 'uploadform': uploadform, 'searchform': searchform, 'is_searching': False, 'query_string': q, 'will_select_format': request.GET.get('select_format'), 'popular_tags': popular_tags_for_model(Image), 'collections': collections, })
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))
from __future__ import absolute_import, unicode_literals import PIL.Image from django.core.files.images import ImageFile from django.utils.six import BytesIO from tuiuiu.tuiuiuimages import get_image_model Image = get_image_model() def get_test_image_file(filename='test.png', colour='white', size=(640, 480)): f = BytesIO() image = PIL.Image.new('RGB', size, colour) image.save(f, 'PNG') return ImageFile(f, name=filename) def get_test_image_file_jpeg(filename='test.jpg', colour='white', size=(640, 480)): f = BytesIO() image = PIL.Image.new('RGB', size, colour) image.save(f, 'JPEG') return ImageFile(f, name=filename)
from __future__ import absolute_import, unicode_literals from tuiuiu.tuiuiucore.permission_policies.collections import CollectionOwnershipPermissionPolicy from tuiuiu.tuiuiuimages import get_image_model from tuiuiu.tuiuiuimages.models import Image permission_policy = CollectionOwnershipPermissionPolicy( get_image_model(), auth_model=Image, owner_field_name='uploaded_by_user')