{"id":19073109,"url":"https://github.com/lowerdeez/ok-images","last_synced_at":"2025-04-28T18:56:47.402Z","repository":{"id":47183823,"uuid":"322291677","full_name":"LowerDeez/ok-images","owner":"LowerDeez","description":"WebP extensions for django-versatileimagefield","archived":false,"fork":false,"pushed_at":"2022-02-07T16:00:52.000Z","size":154,"stargazers_count":5,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-28T18:56:39.924Z","etag":null,"topics":["django","django-versatileimagefield","django-webp","image-models","image-optimization","images","python","webp"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LowerDeez.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-17T12:42:42.000Z","updated_at":"2023-07-13T07:12:28.000Z","dependencies_parsed_at":"2022-09-13T14:20:13.588Z","dependency_job_id":null,"html_url":"https://github.com/LowerDeez/ok-images","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LowerDeez%2Fok-images","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LowerDeez%2Fok-images/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LowerDeez%2Fok-images/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LowerDeez%2Fok-images/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LowerDeez","download_url":"https://codeload.github.com/LowerDeez/ok-images/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251372466,"owners_count":21578964,"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","django-versatileimagefield","django-webp","image-models","image-optimization","images","python","webp"],"created_at":"2024-11-09T01:45:27.688Z","updated_at":"2025-04-28T18:56:47.386Z","avatar_url":"https://github.com/LowerDeez.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"===============================\ndjango-ok-images |PyPI version|\n===============================\n\n|Build Status| |Code Health| |Python Versions| |PyPI downloads| |license| |Project Status|\n\nWebP sizers and filters for `django-versatileimagefield`_. Custom image field with direct access to created images through readable names and model mixin to inherit. Helper utils to delete created images, clear cache and warm images.\n\nInstallation\n============\n\nInstall with pip:\n\n.. code:: shell\n\n    $ pip install django-ok-images django-versatileimagefield\n\nUpdate INSTALLED_APPS:\n\n.. code:: python\n\n    INSTALLED_APPS = [\n        ...\n        'versatileimagefield',\n        ...\n    ]\n\n\n\nAvailable settings\n==================\n\n``IMAGE_ALLOWED_EXTENSIONS`` - Extensions for `OptimizedImageField`'s `FileExtensionValidator`.\n\n``IMAGE_MAX_FILE_SIZE`` - Max file size of uploaded images in megabytes. Default to `10`.\n\n``IMAGE_OPTIMIZE_QUALITY`` - Quality to optimize an uploaded image.\n\n``IMAGE_CREATE_ON_DEMAND`` - Custom value for `django-versatileimagefield`_ `create_images_on_demand` setting.\n\n``IMAGE_PLACEHOLDER_PATH`` - Default placeholder path for `django-versatileimagefield`_.\n\n``IMAGE_RGBA_CHANGE_BACKGROUND`` - Changes background of RGBA images to white color.\n\n``IMAGE_LOSSLESS`` - Image lossless configuration. Default to `False`.\n\nHow to enable image optimization through TinyPNG:\n-------------------------------------------------\n\n``TINYPNG_API_KEY_FUNCTION`` - Path to function, which returns TinyPNG api key.\n\n``TINYPNG_API_KEY`` - TinyPNG api key.\n\n\nHow to use\n==========\n\nWebP sizers and filter:\n-----------------------\n\nAdd next file in any app to register sizers and filters (`more about sizers and filters \u003chttps://django-versatileimagefield.readthedocs.io/en/latest/writing_custom_sizers_and_filters.html#registering-sizers-and-filters\u003e`_):\n\n.. code:: python\n\n    # versatileimagefield.py\n\n    from ok_images.contrib.versatileimagefield.versatileimagefield import *\n\n\nFields:\n-------\n\nThere is an ``OptimizedImageField``, inherited from `VersatileImageField \u003chttps://django-versatileimagefield.readthedocs.io/en/latest/model_integration.html#model-integration\u003e`_.\n\nExample of usage:\n\nAdd next settings (`more about rendition key sets \u003chttps://django-versatileimagefield.readthedocs.io/en/latest/drf_integration.html#reusing-rendition-key-sets\u003e`_):\n\n.. code:: python\n\n    # settings.py\n\n    VERSATILEIMAGEFIELD_RENDITION_KEY_SETS = {\n        'product': [\n            ('full_size', 'url'),\n            ('desktop', 'crop__460x430'),\n            ('catalog_preview', 'crop__180x180'),\n\n            # webp\n            ('desktop_webp', 'crop_webp__460x430'),\n            ('catalog_preview_webp', 'crop_webp__180x180'),\n        ],\n    }\n\nDefine a model like this:\n\n.. code:: python\n\n    # models.py\n    from ok_images.fields import OptimizedImageField\n    \n\n    class Product(models.Model):\n        image_sizes = 'product'  # could be set as a global rendition key set for an each image field\n\n        image = OptimizedImageField(\n            _('Image'),\n            ppoi_field='ppoi',\n            blank=True,\n            null=True,\n            # Optional keyword arguments with default values\n            image_sizes_serializer=VersatileImageFieldSerializer,  # from versatileimagefield.serializers import VersatileImageFieldSerializer\n            image_sizes='product',  # some of keys, defined in VERSATILEIMAGEFIELD_RENDITION_KEY_SETS setting\n            create_on_demand=True,  # enables or disables on-demand image creation\n        )\n        ppoi = PPOIField(\n            verbose_name=_('PPOI')\n        )\n\nIf ``image_sizes`` is not defined, uses next default rendition key set:\n\n.. code:: python\n\n    IMAGE_DEFAULT_RENDITION_KEY_SET = [\n        ('full_size', 'url'),\n    ]\n\nHow to access generated previews:\n\n.. code:: python\n\n    product.image.full_size\n    product.image.catalog_preview\n    product.image.desktop_webp\n\n\nUtils:\n------\n\n``delete_all_created_images`` - delete all created images (can be skipped with ``delete_images`` argument) and clear cache for passed models.\n\n``warm_images`` - creates all sized images for a given instance or queryset with passed rendition key set.\n\n.. code:: python\n    \n    # anywhere.py\n    from ok_images.utils import delete_all_created_images, warm_images\n\t\t\n    \t\n    delete_all_created_images(Product, delete_images = False)\n    warm_images(product, 'product')\n\n    # `rendition_key_set` could be taken from field's or model's attrbiute `image_sizes`, otherwise uses default key set\n    warm_images(Product.objects.all())\n\n\nAsync image warming:\n--------------------\n\n`tasks.py`:\n\n.. code:: python\n\n    from ok_images.utils import warm_images\n\n    @app.task\n    def images_warmer_task(product_pk: int):\n        from store.models import Product\n        product = Product.objects.get(pk=product_pk)\n        warm_images(\n            instance_or_queryset=product,\n            image_attr='image'\n        )\n\n\n`models.py`:\n\n.. code:: python\n   \n    from .tasks import images_warmer_task\n    \t\n    \t\n    def images_warmer(product):\n        images_warmer_task.delay(product.pk)\n\t\n\t\t\n    class Product(models.Model):\n        image_sizes = 'product'\n\n        image = OptimizedImageField(\n            _('Image'),\n            ppoi_field='ppoi',\n            blank=True,\n            null=True,\n            images_warmer=images_warmer\n        )\n\n\n.. |PyPI version| image:: https://badge.fury.io/py/django-ok-images.svg\n   :target: https://badge.fury.io/py/django-ok-images\n.. |Build Status| image:: https://github.com/LowerDeez/ok-images/workflows/Upload%20Python%20Package/badge.svg\n   :target: https://github.com/LowerDeez/ok-images/\n   :alt: Build status\n.. |Code Health| image:: https://api.codacy.com/project/badge/Grade/e5078569e40d428283d17efa0ebf9d19\n   :target: https://www.codacy.com/app/LowerDeez/ok-images\n   :alt: Code health\n.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/django-ok-images.svg\n   :target: https://pypi.org/project/django-ok-images/\n   :alt: Python versions\n.. |license| image:: https://img.shields.io/pypi/l/django-ok-images.svg\n   :alt: Software license\n   :target: https://github.com/LowerDeez/ok-images/blob/master/LICENSE\n.. |PyPI downloads| image:: https://img.shields.io/pypi/dm/django-ok-images.svg\n   :alt: PyPI downloads\n.. |Project Status| image:: https://img.shields.io/pypi/status/django-ok-images.svg\n   :target: https://pypi.org/project/django-ok-images/\n   :alt: Project Status\n\n.. _django-versatileimagefield: https://github.com/respondcreate/django-versatileimagefield\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flowerdeez%2Fok-images","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flowerdeez%2Fok-images","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flowerdeez%2Fok-images/lists"}