Skip to content

minor type in readme #292

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 4, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 57 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,29 @@

# Django Standardized Image Field

Django Field that implement the following features:
## Why would I want this?

* Django-Storages compatible (S3)
* Resize images to different sizes
This is a drop-in replacement for the [Django ImageField](https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.ImageField) that provides a standardized way to handle image uploads.
It is designed to be as easy to use as possible, and to provide a consistent interface for all image fields.
It allows images to be presented in various size variants (eg:thumbnails, mid, and hi-res versions)
and it provides a way to handle images that are too large with validators.


## Features

Django Standardized Image Field implements the following features:

* [Django-Storages](https://django-storages.readthedocs.io/en/latest/) compatible (eg: S3, Azure, Google Cloud Storage, etc)
* Resizes images to different sizes
* Access thumbnails on model level, no template tags required
* Preserves original image
* Asynchronous rendering (Celery & Co)
* Restrict accepted image dimensions
* Rename files to a standardized name (using a callable upload_to)
* Preserves original images
* Can be rendered asynchronously (ie as a [Celery job](https://realpython.com/asynchronous-tasks-with-django-and-celery/))
* Restricts acceptable image dimensions
* Renames a file to a standardized name format (using a callable `upload_to` function, see below)

## Installation

Simply install the latest stable package using the command
Simply install the latest stable package using the following command:

```bash
pip install django-stdimage
Expand All @@ -28,11 +38,13 @@ and add `'stdimage'` to `INSTALLED_APP`s in your settings.py, that's it!

## Usage

Now it's instally you can use either: `StdImageField` or `JPEGField`.

`StdImageField` works just like Django's own
[ImageField](https://docs.djangoproject.com/en/dev/ref/models/fields/#imagefield)
except that you can specify different sized variations.
except that you can specify different size variations.

The `JPEGField` works similar to the `StdImageField` but all size variations are
The `JPEGField` is identical to the `StdImageField` but all images are
converted to JPEGs, no matter what type the original file is.

### Variations
Expand All @@ -58,7 +70,7 @@ class MyModel(models.Model):
# is the same as dictionary-style call
image = StdImageField(upload_to='path/to/img', variations={'thumbnail': (100, 75)})

# variations are converted to JPEGs
# JPEGField variations are converted to JPEGs.
jpeg = JPEGField(
upload_to='path/to/img',
variations={'full': (None, None), 'thumbnail': (100, 75)},
Expand All @@ -77,23 +89,40 @@ class MyModel(models.Model):
}, delete_orphans=True)
```

For using generated variations in templates use `myimagefield.variation_name`.
To use these variations in templates use `myimagefield.variation_name`.

Example:

```html
<a href="{{ object.myimage.url }}"><img alt="" src="{{ object.myimage.thumbnail.url }}"/></a>
```

### Utils
### Upload to function

You can use a function for the `upload_to` argument. Using [Django Dynamic Filenames][dynamic_filenames].[dynamic_filenames]: https://github.com/codingjoe/django-dynamic-filenames

Since version 4 the custom `upload_to` utils have been dropped in favor of
[Django Dynamic Filenames][dynamic_filenames].
This allows images to be given unique paths and filenames based on the model instance.

[dynamic_filenames]: https://github.com/codingjoe/django-dynamic-filenames
Example

```python
from django.db import models
from stdimage import StdImageField
from dynamic_filenames import FilePattern

upload_to_pattern = FilePattern(
filename_pattern='my_model/{app_label:.25}/{model_name:.30}/{uuid:base32}{ext}',
)


class MyModel(models.Model):
# works just like django's ImageField
image = StdImageField(upload_to=upload_to_pattern)
```

### Validators
The `StdImageField` doesn't implement any size validation. Validation can be specified using the validator attribute
The `StdImageField` doesn't implement any size validation out-of-the-box.
However, Validation can be specified using the validator attribute
and using a set of validators shipped with this package.
Validators can be used for both Forms and Models.

Expand All @@ -120,9 +149,9 @@ Django [dropped support](https://docs.djangoproject.com/en/dev/releases/1.3/#del
for automated deletions in version 1.3.

Since version 5, this package supports a `delete_orphans` argument. It will delete
orphaned files, should a file be delete or replaced via Django form or and object with
a `StdImageField` be deleted. It will not be deleted if the field value is changed or
reassigned programatically. In those rare cases, you will need to handle proper deletion
orphaned files, should a file be deleted or replaced via a Django form and the object with
the `StdImageField` be deleted. It will not delete files if the field value is changed or
reassigned programatically. In these rare cases, you will need to handle proper deletion
yourself.

```python
Expand All @@ -141,10 +170,10 @@ class MyModel(models.Model):

### Async image processing
Tools like celery allow to execute time-consuming tasks outside of the request. If you don't want
to wait for your variations to be rendered in request, StdImage provides your the option to pass a
async keyword and a util.
Note that the callback is not transaction save, but the file will be there.
This example is based on celery.
to wait for your variations to be rendered in request, StdImage provides you the option to pass an
async keyword and a 'render_variations' function that triggers the async task.
Note that the callback is not transaction save, but the file variations will be present.
The example below is based on celery.

`tasks.py`:
```python
Expand Down Expand Up @@ -177,19 +206,18 @@ def image_processor(file_name, variations, storage):
class AsyncImageModel(models.Model):
image = StdImageField(
# above task definition can only handle one model object per image filename
upload_to='path/to/file/',
upload_to='path/to/file/', # or use a function
render_variations=image_processor # pass boolean or callable
)
processed = models.BooleanField(default=False) # flag that could be used for view querysets
```

### Re-rendering variations
You might want to add new variations to a field. That means you need to render new variations for missing fields.
You might have added or changed variations to an existing field. That means you will need to render new variations.
This can be accomplished using a management command.
```bash
python manage.py rendervariations 'app_name.model_name.field_name' [--replace] [-i/--ignore-missing]
```
The `replace` option will replace all existing files.
The `ignore-missing` option will suspend missing source file errors and keep
rendering variations for other files. Othervise command will stop on first
missing file.
The `ignore-missing` option will suspend 'missing source file' errors and keep
rendering variations for other files. Otherwise, the command will stop on first missing file.