Skip to content

Commit

Permalink
Merge pull request #252 from uploadcare/feature/234-new_uploader
Browse files Browse the repository at this point in the history
New uploader widget, closes #234
  • Loading branch information
evgkirov authored Dec 28, 2023
2 parents e0abb58 + 37cc7db commit 824c1b6
Show file tree
Hide file tree
Showing 26 changed files with 833 additions and 111 deletions.
8 changes: 8 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
root = true

[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8

40 changes: 40 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,53 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [5.0.0](https://github.com/uploadcare/pyuploadcare/compare/v4.3.0...v5.0.0) - 2023-12-28

In version 5.0, we introduce a new [file uploader](https://uploadcare.com/docs/file-uploader/), which is now the default for Django projects. If you prefer to continue using the old jQuery-based widget, you can enable it by setting the `use_legacy_widget` option in your configuration:

```python
UPLOADCARE = {
...,
"use_legacy_widget": True,
"legacy_widget": {
"version": "3.x",
}
}
```

Additionally, please take note that some settings have been renamed in this update (see the next section).

### Breaking Changes

- Python 3.6 and 3.7 are no longer supported.
- Django 1.11, 2.0, and 2.1 are no longer supported.
- [Pydantic](https://docs.pydantic.dev) has been updated to Version 2. Projects dependent on Pydantic Version 1 may encounter errors due to incompatibility between Versions 1 and 2.
- Removed `tox.ini`. The recommended method for running tests locally is now through [act](https://github.com/nektos/act) with Docker.

- for Django settings (`UPLOADCARE = {...}`):
- `widget_*` settings were renamed and moved:
- `UPLOADCARE["widget_version"]` to `UPLOADCARE["legacy_widget"]["version"]`
- `UPLOADCARE["widget_build"]` to `UPLOADCARE["legacy_widget"]["build"]`
- `UPLOADCARE["widget_variant"]` to `UPLOADCARE["legacy_widget"]["build"]` (this is not a typo: former `widget_build` and `widget_variant` settings were equialent)
- `UPLOADCARE["widget_url"]` to `UPLOADCARE["legacy_widget"]["override_js_url"]` and works regardless of `use_hosted_assets` value.

- for `pyuploadcare.dj.conf`:
- Individual variables were moved into one dict called `config`. If you've accessed these settings from `pyuploadcare.dj.conf` module in your code, please migrate:
- `pub_key` to `config["pub_key"]`
- `secret` to `config["secret"]`
- `cdn_base` to `config["cdn_base"]`
- `upload_base_url` to `config["upload_base_url"]`
- `use_hosted_assets` to `config["use_hosted_assets"]`
- `widget_version` to `config["legacy_widget"]["version"]`
- `widget_build` to `config["legacy_widget"]["build"]`
- `uploadcare_js` to `get_legacy_widget_js_url()`
- Gone from `pyuploadcare.dj.conf`:
- `widget_filename`
- `hosted_url`
- `local_url`

- for `pyuploadcare.dj.forms`:
- `FileWidget` renamed to `LegacyFileWidget`. `FileWidget` is an all-new implementation now.
- By default, `FileWidget` is used. To use `LegacyFileWidget`, please set `UPLOADCARE["use_legacy_widget"]` to `True`

### Added

- Added Python 3.12 and Django 5.0 to the test matrix.
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2022 Uploadcare, Inc
Copyright (c) 2023 Uploadcare, Inc

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
14 changes: 13 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,20 @@ test-django:
test-integration:
poetry run pytest tests/integration --cov=pyuploadcare

test-with-github-actions:
test_with_github_actions:
act -W .github/workflows/test.yml --container-architecture linux/amd64

docs_html:
poetry run sh -c "cd docs && make html"

run_django:
poetry run python tests/test_project/manage.py migrate
poetry run python tests/test_project/manage.py runserver

update_bundled_static:
blocks_version=$$(DJANGO_SETTINGS_MODULE=tests.test_project.settings poetry run python -c "from pyuploadcare.dj.conf import DEFAULT_CONFIG; print(DEFAULT_CONFIG['widget']['version'])"); \
curl "https://cdn.jsdelivr.net/npm/@uploadcare/blocks@$${blocks_version}/web/blocks.min.js" -o pyuploadcare/dj/static/uploadcare/blocks.min.js; \
curl "https://cdn.jsdelivr.net/npm/@uploadcare/blocks@$${blocks_version}/web/lr-file-uploader-inline.min.css" -o pyuploadcare/dj/static/uploadcare/lr-file-uploader-inline.min.css; \
curl "https://cdn.jsdelivr.net/npm/@uploadcare/blocks@$${blocks_version}/web/lr-file-uploader-minimal.min.css" -o pyuploadcare/dj/static/uploadcare/lr-file-uploader-minimal.min.css; \
curl "https://cdn.jsdelivr.net/npm/@uploadcare/blocks@$${blocks_version}/web/lr-file-uploader-regular.min.css" -o pyuploadcare/dj/static/uploadcare/lr-file-uploader-regular.min.css

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ You can find an example project [here](https://github.com/uploadcare/pyuploadcar

```

![](https://ucarecdn.com/dbb4021e-b20e-40fa-907b-3da0a4f8ed70/-/resize/800/manual_crop.png)
![](https://ucarecdn.com/f0894ef2-352e-406a-8279-737dd6e1f10c/-/resize/800/manual_crop.png)

## Documentation

Expand Down
4 changes: 3 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
# html_theme_options = {}
html_theme_options = {
"sidebar_width": "240px",
}

# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
Expand Down
2 changes: 1 addition & 1 deletion docs/core_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ List file groups::
print(file_group.info)

Delete file groups
----------------
------------------

Delete file groups::

Expand Down
160 changes: 134 additions & 26 deletions docs/django-widget.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,75 @@ Django Widget
Settings
--------

Besides required ``pub_key``, ``secret`` settings there are optional settings,
for example, ``widget_version`` or ``widget_build``:
The minimal configuration for a Django project using Uploadcare looks like this:

.. code-block:: python
UPLOADCARE = {
'pub_key': 'demopublickey',
'secret': 'demoprivatekey',
'widget_version': '3.x', // ~= 3.0 (latest)
'widget_build': 'min', // without jQuery
'cdn_base': 'https://cdn.mycompany.com',
"pub_key": "<your public key>",
"secret": "<your private key>",
}
PyUploadcare takes assets from Uploadcare CDN by default, e.g.:
You can generate these keys in your project settings on the `Uploadcare dashboard`_.

In addition to the required settings `pub_key` and `secret`, there are several optional settings available.

Below is the full default configuration:

.. code-block:: python
UPLOADCARE = {
"pub_key": "",
"secret": "",
"cdn_base": None,
"upload_base_url": None,
"signed_uploads": False,
"use_legacy_widget": False,
"use_hosted_assets": True,
"widget": {
"version": "0.30.7",
"variant": "regular",
"build": "min",
"options": {},
"override_js_url": None,
"override_css_url": {
"regular": None,
"inline": None,
"minimal": None,
},
},
"legacy_widget": {
"version": "3.x",
"build": "full.min",
"override_js_url": None,
},
}
PyUploadcare takes assets from CDN by default, e.g.:

.. code-block:: html

<script src="https://ucarecdn.com/widget/x.y.z/uploadcare/uploadcare.full.min.js"></script>
<script type="module">
import * as LR from "https://cdn.jsdelivr.net/npm/@uploadcare/[email protected]/web/blocks.min.js";
LR.registerBlocks(LR);
</script>

<!-- ... -->

<lr-file-uploader-inline
css-src="https://cdn.jsdelivr.net/npm/@uploadcare/[email protected]/web/lr-file-uploader-regular.min.css"
ctx-name="my-uploader"
></lr-file-uploader-inline>


If you don't want to use hosted assets you have to turn off this feature:

.. code-block:: python
UPLOADCARE = {
# ...
'use_hosted_assets': False,
"use_hosted_assets": False,
}
In this case local assets will be used.
Expand All @@ -46,8 +89,14 @@ widget url:
UPLOADCARE = {
# ...
'use_hosted_assets': False,
'widget_url': 'http://path.to/your/widget.js',
"widget": {
"override_js_url": "http://path.to/your/blocks.js",
"override_css_url": {
"regular": "http://path.to/your/lr-file-uploader-regular.css",
"inline": "http://path.to/your/lr-file-uploader-inline.css",
"minimal": "http://path.to/your/lr-file-uploader-minimal.css",
},
},
}
`Uploadcare widget`_ will use default upload handler url, unless you specify:
Expand All @@ -56,10 +105,54 @@ widget url:
UPLOADCARE = {
# ...
'upload_base_url': 'http://path.to/your/upload/handler',
"upload_base_url": "http://path.to/your/upload/handler",
}
If you have signed uploads enabled in your Uploadcare project, widget-based uploads will fail unless you enable the ``signed_uploads`` setting in your Django project::
Use ``widget_options`` to pass arbitrary `options`_ to the file uploader:

.. code-block:: python
UPLOADCARE = {
# ...
"widget": {
"options": {
"source-list": "local,url,camera",
"camera-mirror": True,
},
},
}
.. _django-legacy-widget-settings-ref:

Settings for legacy widget
--------------------------

If you want to use our legacy jQuery-widget, you can enable it in settings:

.. code-block:: python
UPLOADCARE = {
"pub_key": "<your public key>",
"secret": "<your private key>",
"use_legacy_widget": True,
}
Settings that are specific to the legacy widget are prefixed with ``legacy_``:

.. code-block:: python
UPLOADCARE = {
# ...
"use_legacy_widget": True,
"legacy_widget": {
"version": "3.x", # ~= 3.0 (latest)
"build": "min", # without jQuery
"override_js_url": "http://path.to/your/uploadcare.js",
},
}
If you have signed uploads enabled in your Uploadcare project, widget-based uploads will fail unless you enable the ``signed_uploads`` setting in your Django project:

.. code-block:: python
Expand Down Expand Up @@ -89,7 +182,7 @@ These fields play by common Django rules. South migrations are supported.

.. code-block:: python
photo.photo_2x3 = File('a771f854-c2cb-408a-8c36-71af77811f3b')
photo.photo_2x3 = File("a771f854-c2cb-408a-8c36-71af77811f3b")
photo.save()
photo.photo_2x3.store()
Expand Down Expand Up @@ -135,30 +228,43 @@ image. Consult `widget documentation`_ regarding setting up the manual crop:
photo = ImageField(blank=True, manual_crop="")
.. image:: https://ucarecdn.com/93b254a3-8c7a-4533-8c01-a946449196cb/-/resize/800/manual_crop.png

.. _django-widget-models-filegroupfield-ref:

.. _django-widget-models-imagefield-advanced-ref:

Advanced widget options
~~~~~~~~~~~~~~~~~~~~~~~

You can pass any widget options via ``FileWidget``'s attrs argument:
You can pass any widget `options`_ via ``FileWidget``'s attrs argument:

.. code-block:: python
from django import forms
from pyuploadcare.dj.forms import FileWidget, ImageField
# optional. provide advanced widget options: https://uploadcare.com/docs/uploads/widget/config/#options
# optional. provide advanced widget options:
# https://uploadcare.com/docs/file-uploader/configuration/
# https://uploadcare.com/docs/file-uploader/options/
class CandidateForm(forms.Form):
photo = ImageField(widget=FileWidget(attrs={
'data-cdn-base': 'https://cdn.super-candidates.com',
'data-image-shrink': '1024x1024',
"source-list": "local,url,camera",
"camera-mirror": True,
}))
Use ``LegacyFileWidget`` whenever you want to switch back to jQuery-based
widget on a field-by-field basis without turning it on globally (using
``"use_legacy_widget": True``).

.. code-block:: python
from django import forms
from pyuploadcare.dj.forms import LegacyFileWidget, ImageField
class CandidateForm(forms.Form):
photo = ImageField(widget=LegacyFileWidget)
.. _django-widget-models-filegroupfield-ref:

FileGroupField
~~~~~~~~~~~~~~
Expand Down Expand Up @@ -196,5 +302,7 @@ It stores uploaded images as a group:
photos = ImageGroupField()
.. _widget documentation: https://uploadcare.com/docs/uploads/widget/crop_options/
.. _TextField: https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.TextField
.. _Uploadcare dashboard: https://app.uploadcare.com/
.. _options: https://uploadcare.com/docs/file-uploader/options/
.. _widget documentation: https://uploadcare.com/docs/file-uploader/options/#crop-preset
.. _TextField: https://docs.djangoproject.com/en/4.2/ref/models/fields/#textfield
14 changes: 8 additions & 6 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,19 @@ You can find an example project `here`_.
class Candidate(models.Model):
photo = ImageField(blank=True, manual_crop="")
photo = ImageField(blank=True, manual_crop='4:3')
# optional. provide advanced widget options: https://uploadcare.com/docs/uploads/widget/config/#options
# optional. provide advanced widget options:
# https://uploadcare.com/docs/file-uploader/configuration/
# https://uploadcare.com/docs/file-uploader/options/
class CandidateForm(forms.Form):
photo = ImageFormField(widget=FileWidget(attrs={
'data-cdn-base': 'https://cdn.super-candidates.com',
'data-image-shrink': '1024x1024',
photo = ImageField(widget=FileWidget(attrs={
'source-list': 'local,url,camera',
'camera-mirror': True,
}))
.. image:: https://ucarecdn.com/dbb4021e-b20e-40fa-907b-3da0a4f8ed70/-/resize/800/manual_crop.png
.. image:: https://ucarecdn.com/f0894ef2-352e-406a-8279-737dd6e1f10c/-/resize/800/manual_crop.png

Features
========
Expand Down
Loading

0 comments on commit 824c1b6

Please sign in to comment.