Coder Social home page Coder Social logo

django-webp's Introduction

django-webp

Speeds up static file load times by generating a webp image to load to a webpage instead of a jpg, gif or png

Build Status Coverage Status

Usage

Load the webp module in your template and use the webp templatetag to point to the image you want to convert.

{% load webp %}

{# Use webp as you would use static templatetag #}
<img src="{% webp 'path/to/your/image.png' %}" alt="image" />
<!--
If the browser has support, generates:
<img src="/static/WEBP_CACHE/path/to/your/image.webp" alt="image" />

else, generates:
<img src="/static/path/to/your/image.png" alt="image" />
-->

Installation

First, if you are using a version of Pillow <= 9.3.0, you must install webp support since earlier versions of Pillow do not have webp support built-in. In ubuntu, you can install via apt-get:

apt-get install libwebp-dev

Please, check the official guide for the other systems.

Then, install django-webp.

pip install django-webp

add it to INSTALLED_APPS configuration

INSTALLED_APPS = (
    'django.contrib.staticfiles',
    'django_webp',
    '...',
)

edit your installation of Whitenoise to use our slightly modded version of it

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django_webp.middleware.ModdedWhiteNoiseMiddleware',
    '...',
]

add the django_webp context processor

TEMPLATES = [
    {
        '...'
        'OPTIONS': {
            'context_processors': [
                '...',
                'django_webp.context_processors.webp',
            ],
        },
    },
]

Settings

The following Django-level settings affect the behavior of the library

  • WEBP_CHECK_URLS

    When set to True, urls that link to externally stored images (i.e. images hosted by another site) are checked to confirm if they are valid image links. Ideally, this should temporarily be set to True whenever the WEBP_CACHE has been cleaned or if there has been substantial changes to your project's template files. This defaults to False.

Possible Issues

  • django-webp uses Pillow to convert the images. If you’ve installed the libwebp-dev after already installed Pillow, it’s necessary to uninstall and install it back because it needs to be compiled with it.
  • This package was built specifically for production environments that use Whitenoise for serving static files so there currently isn't support for serving files via dedicated servers or through cloud services

Cleaning the cache

You can clean the cache running:

python manage.py clean_webp_images

django-webp's People

Contributors

afarzat-ed avatar andrefarzat avatar bimmui avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

django-webp's Issues

How to use it with DRF?

I would like to use this package in DRF. Can you please provide a guide for using it with DRF. So, how can we build an absolute webp image URL for API?

Also, can we integrate in an existing project, or I have to remove all the images or something else.

WEBP image could not be saved in

I am using Pillow 10.0.0, whitnoise 6.5.0, Django 4.2.3, django-webp 2.1.1.

When running locally with the no WEBP_CACHE the images are created in WEB_CACHE/images but are not accessible. Log output is Not Found: /static/WEBP_CACHE/filename. If I restart the application images that have been created in the WEB_CACHE/images directory are loaded, however images that have not been created in this directory will not load. They will load if the application is restarted again.

I was mostly able to fix this by creating a python command that looped through the images in the static directory and called the webp function in dajngo_webp.tempatetags.webp.py.

When deployed if I run this custom command or if I attempt to use the package as it is I get and error WEBP image could not be saved in app/project/staticfiles/WEBP_CACHE/images/imagename. The deployment is to openshift.

When I run collectstatic the path is "/app/project_nam/staticfiles", could the slash at the beginning be the difference?

404 Not found error

I have a problem serving media files with webp tag. Just followed steps in documentation. Maybe I am missing something?

My settings:

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
STATICFILES_DIRS = (
    ("css", os.path.join(STATIC_ROOT, 'css/')),
    ("images", os.path.join(STATIC_ROOT, 'images/')),
    ("js", os.path.join(STATIC_ROOT, 'js/'))
)

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')

Template example:

{% load i18n webp %}
<h1 class="display-5 fw-bold text-body-emphasis lh-1 mb-3">{% translate 'Categories' %}</h1>
<div class="row row-cols-2 row-cols-lg-4">
    {% for category in categories %}
    <div class="col mb-4 text-center">
        <a href="{{ category.get_absolute_url }}">
            <img src="{% webp category.image.url %}" class="card-img-top" alt="{% if category.image_alt %}{{ category.image_alt }}{% else %}{{ category.name }}{% endif %}">
        </a>
        
        <h2 class="card-text h4 mt-3">
            <a class="nav-link" href="{{ category.get_absolute_url }}">
                {{ category.name }}
            </a>
        </h2>
    </div>
    {% endfor %}
</div>

Output error:

[26/Aug/2023 11:43:23] "GET /static/media/images/categories/cat_totebag.jpg HTTP/1.1" 404 1876
[26/Aug/2023 11:43:23] "GET /static/media/images/categories/cat_rolltop.jpg HTTP/1.1" 404 1876
[26/Aug/2023 11:43:23] "GET /static/media/images/categories/cat_backpack.jpg HTTP/1.1" 404 1879
[26/Aug/2023 11:43:23] "GET /static/media/images/categories/cat_duffelbag.jpg HTTP/1.1" 404 1882

So "/static/" is added to the path, when correct path is /media/images/categories/img.jpg. With static tag media serving correctly and everything is fine

Add Support For Database models.ImageField images stored in /media

In my project, I want to be able to webp images inside /media because Facebook Opengraph and Twitter cards metadata requires filetypes that are not webp. I want my website output to show the webp images while Facebook and Twitter are given the jpeg/png images when not including the webp tag.

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

thumbnail = models.ImageField(blank=True, null=True, max_length=255)

Do something like:

<img src="{% webp object.thumbnail.url %}" />
<img src="/media/test.webp" />

Convert From Webp To Another Format?

If my site uses webp by default, it would be nice for there to be a way to convert to another format if the browser does not support it. Is this currently a feature or can this possibly be worked on?

<img src="/media/test.webp" alt="alt" width="500" height="300">

Becomes

<img src="/media/test.png" alt="alt" width="500" height="300">
<img src="/media/test.jpeg" alt="alt" width="500" height="300">

PII / GDPR Question

I want to make sure with you that this package is legal for PII & GDPR laws. I read online that the user agent string or determining the user browser could violate these laws since it helps identify who the user is based on their browser. I think as long as the user agent is not stored in the database or if there is an option to disable collecting it, it should be okay. Otherwise if it is stored in the database, there should be some way to deal with that like encrypting it. Please let me know. Hopefully the code does not need to be changed at all, and if no changes are needed feel free to close this issue.

Cast STATIC_ROOT to string when joining WEBP_STATIC_ROOT

I'm using STATIC_ROOT as a posix path which is a type native to Python3 - https://docs.python.org/3/library/pathlib.html and in the official Django docs in the base dir. ( https://docs.djangoproject.com/en/4.1/howto/overriding-templates/#overriding-from-the-project-s-templates-directory ):

    BASE_DIR = Path(__file__).resolve().parent.parent.parent
    STATIC_ROOT = BASE_DIR / 'staticfiles'

So django webp fails because it's trying to join a path with a string. If a string is needed, it should be cast to string, or use

os.path.join(STATIC_ROOT, 'string')
#0 1.267   File "/usr/local/lib/python3.10/site-packages/django_webp/templatetags/webp.py", line 11, in <module>
#0 1.269     from django_webp.utils import WEBP_STATIC_URL, WEBP_STATIC_ROOT, WEBP_DEBUG, WEBP_CONVERT_MEDIA_FILES
#0 1.269   File "/usr/local/lib/python3.10/site-packages/django_webp/utils.py", line 11, in <module>
#0 1.269     WEBP_STATIC_ROOT = STATIC_ROOT + WEBP_STATIC_ROOT
#0 1.269 TypeError: unsupported operand type(s) for +: 'PosixPath' and 'str'

move covert logic to storage

right now the covert logic in template tags level, in debug env it's awesome.

but in production env, it's bad to dynamic generate webp, we need do this in collectstatic step.

so the better way is move covert logic to custom storage.

better to extend ManifestStaticFilesStorage class.

in json file would be like below:

{'foo.png': 'foo.hash.png', 'foo.webp': 'foo.hash.webp'}

Use something other than SHA256?

FIPS or the NIST CNSA standards Recommendations:

https://apps.nsa.gov/iaarchive/programs/iad-initiatives/cnsa-suite.cfm

https://www.keylength.com/en/4/

https://www.safelogic.com/algorithms-part-2-suite-b-cnsa/

Other links:

https://medium.com/@davidtstrauss/stop-using-sha-256-6adbb55c608

https://www.reddit.com/r/privacy/comments/5knrjk/how_secure_is_sha256_encryption/

https://crypto.stackexchange.com/questions/35639/is-sha-256-safe-and-difficult-to-crack

I was reading a Linux Security book and it mentioned how lots of encryption algorithms are preparing for a Quantum computing world where Quantum computers will be able to easily crack weaker encryption algorithms. This is just a suggestion for future proofing this app. Curious to see what you think.

Ed25519 encryption that does not leak private key data like RSA does. Not on NIST list. Protects from side channel and OS attacks. (maybe a good thing if you wear a tin foil hat and don't like the government recommendations above lol). But not might be future proof for quantum computing.

Elliptical curve is probably better than RSA. Something like ecdsa 384.

RSA 3072. Higher RSA key length slows down your PC even though it is better security.

I am not an expert but this would be something to further research.

Or maybe not change SHA256 at all? Maybe it is good enough and I am missing something?

Update browser support

Right now this only supports


WEBP_VALID_BROWSERS = getattr(settings, 'WEBP_VALID_BROWSERS', ['Chrome', 'Opera', 'Opera Mobile'])

However most browsers (except IE) now support WEBP. Should this check be entirely removed?

can't import django-webp, ModuleNotFoundError: No module named 'utils'

^^Traceback (most recent call last):
^^^^  File "C:\Users\brejnak\Desktop\repos\marcom\marcom-strona\manage.py", line 22, in <module>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1381, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1354, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1325, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 929, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 994, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "C:\Users\brejnak\Desktop\repos\marcom\venv\Lib\site-packages\django_webp\templatetags\webp.py", line 20, in <module>
    from utils import (
ModuleNotFoundError: No module named 'utils'

After changing from utils import ( -> from ..utils import (

  File "C:\Users\brejnak\Desktop\repos\marcom\venv\Lib\site-packages\django\core\management\__init__.py", line 442, in execute_from_command_line
^^^^
  File "<frozen importlib._bootstrap>", line 1381, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1354, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1325, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 929, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 994, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "C:\Users\brejnak\Desktop\repos\marcom\venv\Lib\site-packages\django_webp\templatetags\webp.py", line 20, in <module>
        from ..utils import (utility.execute()

ImportError:   File "C:\Users\brejnak\Desktop\repos\marcom\venv\Lib\site-packages\django\core\management\__init__.py", line 436, in execute
cannot import name 'USING_WHITENOISE' from 'django_webp.utils' (C:\Users\brejnak\Desktop\repos\marcom\venv\Lib\site-packages\django_webp\utils.py)

USING_WHITENOISE seems to not be present at all in the project, it's only imported, but not used in /django_webp/templatetags/webp.py

https://github.com/search?q=repo%3Adjango-master%2Fdjango-webp%20USING_WHITENOISE&type=code

Apple Safari / IOS Handling

Is there a way either with this package or in general with django to deal with IOS & safari since it does not support webp as of today? If not, adding an if statement to the template saying if ios/safari then use jpeg/png otherwise use webp. Does this package currently automatically determine if webp is supported on a browser and not use it if it isn't? Otherwise open to other ideas.

Does it check the user agent and deliver a different format? Read the accept headers?

https://caniuse.com/#feat=webp

Update to Python 3 and Django 3

This package seems to not have been updated for a while. How about updating the code to work with the latest python 3 and django 3 versions?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.