Skip to content
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

New uploader widget #252

Merged
merged 48 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
c97e5a9
#234 updated test_project for django
evgkirov Aug 10, 2023
9a0f2bc
added .editorconfig
evgkirov Aug 10, 2023
2c33d91
updated tests/test_project
evgkirov Aug 10, 2023
a4dbe4e
#234 - new widget - proof of concept
evgkirov Aug 10, 2023
0ccfc26
#234 - new widget - more wip
evgkirov Aug 23, 2023
fd0178d
#234 flake8 warnings
evgkirov Aug 24, 2023
70059f7
#234 reworked settings
evgkirov Aug 24, 2023
26f7b07
#234 make flake8 happy again
evgkirov Aug 24, 2023
9b88622
#234 small fixes for the new widget
evgkirov Sep 11, 2023
f7dd0a5
#234 docs'n'stuff
evgkirov Sep 14, 2023
6edd96a
#234 Update HISTORY.md
evgkirov Sep 15, 2023
3506528
#234 Update install.rst
evgkirov Sep 15, 2023
33ef50c
#234 Update install.rst
evgkirov Sep 15, 2023
f70ea22
#234 pass dj_conf.cdn_base to uploader
evgkirov Oct 3, 2023
597f45a
#234 introduce UPLOADCARE["widget_options"]
evgkirov Oct 3, 2023
3bc3f6e
#234 pass dj_conf.upload_base_url to uploader
evgkirov Oct 3, 2023
4b43aa6
#234 don't put css class into lr-config
evgkirov Oct 4, 2023
bc253b9
Merge branch 'main' into feature/234-new_uploader
evgkirov Oct 4, 2023
4066193
fix "C901 'FileWidget.render' is too complex (6)"
evgkirov Oct 4, 2023
16c15c1
#234 bump version (5.0.0-rc1)
evgkirov Oct 5, 2023
a5a78d5
#234 update uploader to 0.26.0
evgkirov Oct 5, 2023
a942388
Merge branch 'main' into feature/234-new_uploader
evgkirov Oct 5, 2023
02285dc
#234 brought back manual_crop for the new uploader (thanks to its rel…
evgkirov Oct 5, 2023
60294bc
#234 update docs
evgkirov Oct 5, 2023
947fd35
#234 update docs [2]
evgkirov Oct 5, 2023
ac11874
#234 Update docs/django-widget.rst
evgkirov Oct 12, 2023
bf7f29c
#234 use 0.x of blocks instead of specific version
evgkirov Oct 12, 2023
99c926a
#234 update docs
evgkirov Oct 12, 2023
6fa2f1f
#234 add update_bundled_static target to Makefile for updating bundle…
evgkirov Oct 12, 2023
f750bb5
#234 refactor pyuploadcare.dj.conf
evgkirov Oct 18, 2023
d32c7c7
#234 updated docs for settings
evgkirov Oct 18, 2023
f04ff53
#234 resolved "move legacy widget below the new widget"
evgkirov Nov 10, 2023
4c647d2
Merge branch 'main' into feature/234-new_uploader
evgkirov Dec 1, 2023
868116b
#234 code format
evgkirov Dec 1, 2023
b4a625d
update signed_uploads feature to use new settings format #234 #262
evgkirov Dec 1, 2023
b75bae0
update blocks to 0.30.2 #234
evgkirov Dec 1, 2023
5192daf
added "make run_django" command
evgkirov Dec 1, 2023
192d10b
#234 update docs
evgkirov Dec 15, 2023
5a32350
#234 add input-required
evgkirov Dec 15, 2023
df34e5b
#234 update blocks to 0.30.5
evgkirov Dec 15, 2023
7765cb3
#234 "Could you also add some styles to the lr-data-output and wrap i…
evgkirov Dec 15, 2023
8890f39
#234 user-agent-integration
evgkirov Dec 15, 2023
383b353
Merge branch 'main' into feature/234-new_uploader
evgkirov Dec 28, 2023
7ce52c9
#234 update docs
evgkirov Dec 28, 2023
ab21ae6
#234 update docs
evgkirov Dec 28, 2023
2383572
#234 lint
evgkirov Dec 28, 2023
2c11276
#234 Blocks 0.30.7
evgkirov Dec 28, 2023
37cc7db
Bump license year.
evgkirov Dec 28, 2023
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
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')
evgkirov marked this conversation as resolved.
Show resolved Hide resolved


# 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',
evgkirov marked this conversation as resolved.
Show resolved Hide resolved
'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