{"id":13448836,"url":"https://github.com/jonasundderwolf/django-image-cropping","last_synced_at":"2025-03-22T18:32:05.401Z","repository":{"id":1629229,"uuid":"2347234","full_name":"jonasundderwolf/django-image-cropping","owner":"jonasundderwolf","description":"Django helper application to easily and non-destructively crop arbitrarily large images in admin and frontend.","archived":false,"fork":false,"pushed_at":"2023-03-05T10:40:13.000Z","size":565,"stargazers_count":552,"open_issues_count":28,"forks_count":131,"subscribers_count":33,"default_branch":"master","last_synced_at":"2025-03-01T22:17:58.277Z","etag":null,"topics":["django","feincms","image-cropping","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"norman/telescope","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jonasundderwolf.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2011-09-08T08:32:23.000Z","updated_at":"2025-01-30T07:56:07.000Z","dependencies_parsed_at":"2023-07-06T10:16:36.262Z","dependency_job_id":null,"html_url":"https://github.com/jonasundderwolf/django-image-cropping","commit_stats":{"total_commits":403,"total_committers":36,"mean_commits":"11.194444444444445","dds":0.5062034739454094,"last_synced_commit":"35690de10d125e66774ad2c0b8100fe88b94def8"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonasundderwolf%2Fdjango-image-cropping","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonasundderwolf%2Fdjango-image-cropping/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonasundderwolf%2Fdjango-image-cropping/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jonasundderwolf%2Fdjango-image-cropping/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jonasundderwolf","download_url":"https://codeload.github.com/jonasundderwolf/django-image-cropping/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245002847,"owners_count":20545505,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","feincms","image-cropping","python"],"created_at":"2024-07-31T06:00:22.196Z","updated_at":"2025-03-22T18:32:00.372Z","avatar_url":"https://github.com/jonasundderwolf.png","language":"Python","funding_links":[],"categories":["Image handling","图片处理","Python","JavaScript"],"sub_categories":[],"readme":"=====================\ndjango-image-cropping\n=====================\n\n.. image:: https://img.shields.io/pypi/v/django-image-cropping.svg\n    :target: https://pypi.python.org/pypi/django-image-cropping\n\n.. image:: https://img.shields.io/pypi/pyversions/django-image-cropping.svg\n    :target: https://pypi.python.org/pypi/django-image-cropping\n\n.. image:: https://img.shields.io/pypi/djversions/django-image-cropping\n    :alt: PyPI - Django Version\n    :target: https://pypi.python.org/pypi/django-image-cropping\n\n.. image:: https://img.shields.io/coveralls/github/jonasundderwolf/django-image-cropping/master\n    :alt: Coveralls branch\n\ndjango-image-cropping is an app for cropping uploaded images via Django's admin backend using `Jcrop\n\u003chttps://github.com/tapmodo/Jcrop\u003e`_.\n\nScreenshot:\n\n.. image:: docs/django_image_cropping_example.png\n    :alt: Screenshot of the cropping\n\ndjango-image-cropping is perfect when you need images with a specific size for your templates but want your\nusers or editors to upload images of any dimension. It presents a selection with a fixed aspect ratio so your users\ncan't break the layout with oddly-sized images.\n\nThe original images are kept intact and only get cropped when they are displayed.\nLarge images are presented in a small format, so even very big images can easily be cropped.\n\nThe necessary fields, widgets and a template tag for displaying the\ncropped image in your templates are provided.\n\nAlso works with `FeinCMS \u003chttps://github.com/feincms/feincms\u003e`_ content types!\n\nInstallation\n============\n\n#. Install django-image-cropping using ``pip``::\n\n    pip install django-image-cropping\n\nBy default ``django-image-cropping`` ships with an ``easy-thumbnails``-backend which requires ``easy-thumbnails`` to also be installed\nand added to the ``INSTALLED_APPS``.\n\nThe `easy-thumbnails` backend requires that you adjust the thumbnail processors in your ``settings``::\n\n    INSTALLED_APPS = [\n        ...\n        'easy_thumbnails',\n        'image_cropping',\n    ]\n\n    from easy_thumbnails.conf import Settings as thumbnail_settings\n    THUMBNAIL_PROCESSORS = (\n        'image_cropping.thumbnail_processors.crop_corners',\n    ) + thumbnail_settings.THUMBNAIL_PROCESSORS\n\n\nConfiguration\n=============\n\nAdd an ``ImageRatioField`` to the model that contains the ``ImageField`` for the images you want to crop.\n\nThe ``ImageRatioField`` simply stores the boundaries of the cropped image.\nIt expects the name of the associated ``ImageField`` and the desired size of the cropped image as arguments.\n\nThe size is passed in as a string and defines the aspect ratio of the selection *as well* as the minimum\nsize for the final image::\n\n    from django.db import models\n    from image_cropping import ImageRatioField\n\n    class MyModel(models.Model):\n        image = models.ImageField(blank=True, upload_to='uploaded_images')\n        # size is \"width x height\"\n        cropping = ImageRatioField('image', '430x360')\n\nYou can configure a `size warning`_ if users try to crop a selection smaller than the defined minimum.\n\nAdmin Integration\n=================\n\nAdd the ``ImageCroppingMixin`` to your ``ModelAdmin``::\n\n    from django.contrib import admin\n    from image_cropping import ImageCroppingMixin\n\n    class MyModelAdmin(ImageCroppingMixin, admin.ModelAdmin):\n        pass\n\n    admin.site.register(MyModel, MyModelAdmin)\n\nIf your setup is correct you should now see the enhanced image widget that provides a selection\narea.\n\n\nBackends\n========\n\ndjango-image-cropping delegates the cropped image generation to a backend.\n\nA backend based on `easy-thumbnails` is provided, but it's possible to use a custom backend.\nThe ``IMAGE_CROPPING_BACKEND`` setting expects a dotted path to a class that implements the required methods.\nYou can omit this setting if you want to use the default backend.\n\nIn case you use a custom backend you can provide an optional dict that will be used to populate the backend's\nconstructor params.\n\nDefault settings::\n\n    IMAGE_CROPPING_BACKEND = 'image_cropping.backends.easy_thumbs.EasyThumbnailsBackend'\n    IMAGE_CROPPING_BACKEND_PARAMS = {}\n\n\nFrontend\n========\n\ndjango-image-cropping provides a templatetag for displaying a cropped thumbnail.\nAny other processor parameter (like ``bw=True`` or ``upscale=True``) will be forwarded to the backend::\n\n    {% cropped_thumbnail yourmodelinstance \"ratiofieldname\" [scale=INT|width=INT|height=INT|max_size=\"INTxINT\"] %}\n\nExample usage::\n\n    {% load cropping %}\n    \u003cimg src=\"{% cropped_thumbnail yourmodel \"cropping\" scale=0.5 %}\"\u003e\n\nOr generate the URL from Python code in your view::\n\n    from image_cropping.utils import get_backend\n    thumbnail_url = get_backend().get_thumbnail_url(\n        yourmodel.image,\n        {\n            'size': (430, 360),\n            'box': yourmodel.cropping,\n            'crop': True,\n            'detail': True,\n        }\n    )\n\n\neasy_thumbnails\n---------------\n\nYou can also use the standard ``easy-thumbnails`` templatetag with the ``box`` parameter::\n\n    {% load thumbnail %}\n    {% thumbnail yourmodel.image 430x360 box=yourmodel.cropping crop detail %}\n\nOr generate the URL from Python code in your view::\n\n    from easy_thumbnails.files import get_thumbnailer\n    thumbnail_url = get_thumbnailer(yourmodel.image).get_thumbnail({\n        'size': (430, 360),\n        'box': yourmodel.cropping,\n        'crop': True,\n        'detail': True,\n    }).url\n\n\nModelForm\n=========\n\nIf you want to use the cropping widget outside the admin, you'll need to define the ``ImageField`` as\nan ``ImageCropField``::\n\n    from django.db import models\n    from image_cropping import ImageCropField, ImageRatioField\n\n    class MyModel(models.Model):\n        image = ImageCropField(blank=True, upload_to='uploaded_images')\n        # size is \"width x height\"\n        cropping = ImageRatioField('image', '430x360')\n\n\nAlternatively, override the widget in your ModelForm (you just need to do one of these two, not both!)::\n\n    from django import forms\n    from image_cropping import ImageCropWidget\n\n    class MyModelForm(forms.ModelForm):\n        class Meta:\n            widgets = {\n                'image': ImageCropWidget,\n            }\n\n\nRemember to include the form media in the ``\u003chead\u003e`` of your HTML::\n\n    \u003chtml\u003e\n      \u003chead\u003e\n        {{ form.media }}\n      \u003c/head\u003e\n      \u003cbody\u003e\n        {{ form }}\n      \u003c/body\u003e\n    \u003c/html\u003e\n\nThe cropping itself happens in the ``ImageRatioField``, the ``ImageCropField`` will still behave like a regular ``ImageField``.\n\nIf you're selectively including or excluding fields from the ModelForm, remember to include the ``ImageRatioField``.\n\n\nMultiple formats\n================\n\nIf you need the same image in multiple formats, simply specify another ``ImageRatioField``.\nThis will allow the image to be cropped twice::\n\n    from image_cropping import ImageRatioField, ImageCropField\n\n    image = ImageCropField(blank=True, upload_to='uploaded_images')\n    # size is \"width x height\"\n    list_page_cropping = ImageRatioField('image', '200x100')\n    detail_page_cropping = ImageRatioField('image', '430x360')\n\nIn your templates, use the corresponding ratio field::\n\n    {% load cropping %}\n    {% cropped_thumbnail yourmodel \"list_page_cropping\" %}\n\n\nForeign Keys\n============\n\nIf you need to crop an image contained within another model, referenced by a ForeignKey, the ``ImageRatioField`` is\ncomposed of the ``ForeignKey`` name, a double underscore, and the ``ImageField`` name::\n\n    from django.db import models\n    from image_cropping.fields import ImageRatioField\n\n    class Image(models.Model):\n        image_field = models.ImageField(upload_to='image/')\n\n    class NewsItem(models.Model):\n        title = models.CharField(max_length=255)\n        image = models.ForeignKey(Image)\n        cropping = ImageRatioField('image__image_field', '120x100')\n\nCropping foreign keys only works in the admin for now, as it reuses the ``raw_id`` widget.\n\n\n.. _free cropping:\n\nFree cropping\n=============\n\nIf you do not need a *fixed* ratio, you can disable this constraint by setting ``free_crop`` to ``True``.\nIn this case the size parameter is the desired minimum and is also used for the size-warning::\n\n    from image_cropping import ImageRatioField, ImageCropField\n\n    image = ImageCropField(blank=True, upload_to='uploaded_images')\n\n    # size is \"width x height\" so a minimum size of 200px x 100px would look like this:\n    min_free_cropping = ImageRatioField('image', '200x100', free_crop=True)\n\nUse the ``max_size`` parameter of the templatetag if you want to limit the display size of a thumbnail::\n\n     \u003cimg src=\"{% cropped_thumbnail image \"cropping_free\" max_size=\"200x200\" %}\" /\u003e\n\n\nDisabling cropping\n==================\n\nIf you want cropping to be optional, use ``allow_fullsize=True`` as an additional keyword argument for your ``ImageRatioField``.\n\nEditors can now switch off cropping by unchecking a checkbox next to the image cropping widget::\n\n     image_with_optional_cropping = ImageRatioField('image', '200x100', allow_fullsize=True)\n\n\nSettings\n========\n\nThumbnail size\n--------------\n\nYou can define the maximum size of the admin preview thumbnail in your ``settings``::\n\n    # size is \"width x height\"\n    IMAGE_CROPPING_THUMB_SIZE = (300, 300)\n\n.. _size warning:\n\nSize warning\n------------\n\nYou can warn users about crop selections that are smaller than the size defined in the ``ImageRatioField``.\nWhen users try to do a smaller selection, a red border appears around the image.\n\nTo use this functionality for a single image add the ``size_warning`` parameter to the ``ImageRatioField``::\n\n    cropping = ImageRatioField('image', '430x360', size_warning=True)\n\nYou can enable this functionality project-wide by adding the following line to your ``settings``::\n\n    IMAGE_CROPPING_SIZE_WARNING = True\n\n\nCustom jQuery\n-------------\n\nBy default the image cropping widget uses the jQuery version vendored with the Django admin.\n\nYou can point to another version using the ``IMAGE_CROPPING_JQUERY_URL`` setting, though compatibility\nissues may arise if your jQuery version differs from the one that is tested against.\n\nYou can also set ``IMAGE_CROPPING_JQUERY_URL`` to ``None`` to disable inclusion of jQuery by the widget.\nYou are now responsible for including ``jQuery`` yourself, both in the frontend and in the admin interface.\n\nCustom backend\n--------------\n\nYou can define a custom backend::\n\n    IMAGE_CROPPING_BACKEND = 'image_cropping.backends.easy_thumbs.EasyThumbnailsBackend'\n\nYou can provide an optional dict that will be used to populate the backend's\nconstructor::\n\n    IMAGE_CROPPING_BACKEND_PARAMS = {'version_suffix': 'thumb'}\n\nSee the built-in backends on Backends_.\n\n\nTesting\n=======\n\n- Setup a virtualenv with one of the supported versions of Python\n- Install the example project: ``pip install -r example/requirements.txt``\n- Run ``pytest``\n- In case you want to test against multiple Python versions install and run ``tox``\n\n\nTroubleshooting\n===============\n\nThe cropping widget is not displayed when using a ``ForeignKey``.\n    Make sure you do **not** add the corresponding image field to ``raw_id_fields``.\n\n\nChangelog\n=========\n\n1.7\n---\n\n- Add support for Django 4.0 (`@jwedel \u003chttps://github.com/jwedel\u003e`_ in `#176 \u003chttps://github.com/jonasundderwolf/django-image-cropping/pull/176\u003e`_)\n\n1.6.2\n-----\n\n- Use the jQuery bundled with Django as the default jQuery for image cropping\n\n1.6.1\n-----\n\n- Add default setting for jquery url to app conf\n\n1.6\n---\n\n- Add support for Django 3.2\n- Add support for Python 3.9\n\n1.5\n---\n\n- Drop support for Python 3.5 (although it should still work)\n- Add support for Django 3.1\n- Minified JS and reduce potential for incompatibility with other django libraries (See #148)\n- Fix formfield_for_dbfield signature (#134)\n- Fix CSS property word separator (#131)\n- Enforce isort in tests\n\n1.4\n---\n\n- Removed more old code\n- Move testing and packaging to GitHub Actions\n\n1.3\n---\n\n- Add support for Django 3.0\n- Drop support for Python \u003c 3.5\n- Drop support for Django \u003c 2.2\n\n1.2\n---\n\n- Add support for Django 2.1\n\n1.1\n---\n\n- Make django-image-cropping compatible with Django 1.11\n\n1.0.4\n-----\n\n- Move and encapsulate the logic for creating cropped thumbnails to a swappable backend. (`@fgmacedo \u003chttps://github.com/fgmacedo\u003e`_ in #92)\n\n1.0\n---\n\n\"If your software is being used in production, it should probably already be 1.0.0.\" (http://semver.org)\n\n0.9\n---\n\nThis release addresses mainly the test coverage and internal stuff.\n\nNoteable (breaking) changes and things to be considered when upgrading from an older version:\n\n- `django-appconf \u003chttps://github.com/jezdez/django-appconf\u003e`_ is now used for handling defaults and settings.\n\n  * **Breaking Change**: JQUERY_URL changed to IMAGE_CROPPING_JQUERY_URL as part of this transition.\n\n- The ``cropped_thumbnail`` tag is now based on Django's ``simple tag``.\n\n  * **Breaking Change**: Arguments for the the tag now need to be put in quotes.\n  * If you are still using Django 1.4 remember that `you can't easily use \u003chttp://stackoverflow.com/q/11804315/630877\u003e`_ ``True`` or ``False`` as template tag arguments.\n\n- Any processor parameter (like bw=True or upscale=True) can be used in the ``cropped_thumbnail`` tag.\n\n- Moved inline css to a dedicated ``image_cropping.css`` style sheet\n\n0.8\n---\n\n- **Minimum** requirements changed to **Django 1.4** and **easy-thumbnails 1.4**\n- Added Python 3 compatibility. Python 2.6 is now the minimum required Python version.\n- Added a `free cropping`_ option, so cropping is no longer restricted to fixed ratios.\n- Removed the deprecated ``CropForeignKey`` field.\n\n0.7\n---\n\n- Made the widget for the ``ImageCropField`` overwritable to allow custom widgets. (Remember to use the ``ImageCroppingMixin`` in the admin as the image cropping widgets are no longer implicitly set.)\n- Updated ``Jcrop`` and ``jQuery`` dependencies.\n- Moved docs to *Read the Docs*: https://django-image-cropping.readthedocs.org\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonasundderwolf%2Fdjango-image-cropping","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjonasundderwolf%2Fdjango-image-cropping","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjonasundderwolf%2Fdjango-image-cropping/lists"}