# bw-file-resubmit
**bw-file-resubmit** is a drop-in replacement for [**django-file-resubmit**](https://github.com/un1t/django-file-resubmit), maintained by the BookWyrm project.
In a Django project you may have forms using `FileField` or `ImageField`. Everything works great, but
when a `ValidationError` is raised, or you want to add some other check before finally submitting the form, you have to reselect all files and images again. This is because HTML `<input type="file">` fields cannot be prepopulated with data due to basic browser security.
**bw-file-resubmit** solves this problem by caching the file and adding it again in the background. It works with `FileField`, `ImageField` and `sorl.thumbnail.ImageField` (see [sorl-thumbnail](https://github.com/jazzband/sorl-thumbnail)).
## How does it work?
Special widgets can be used to replace `FileField` and `ImageField`. When you submit files, every widget saves its file to the cache. When a `ValidationError` is raised, the widgets restore files from cache so the user doesn't have to upload them again.
* `ResubmitFileWidget` can be used in place of `ClearableFileInput`
* `ResubmitImageWidget` can be used in place of `ClearableFileInput`
* `AdminResubmitImageWidget` can be used in place of `AdminFileWidget` (Django) or `AdminImageWidget` (sorl-thumbnail)
* `AdminResubmitMixin` will apply the appropriate widget for all `FileField`s and `ImageField`s
## Installation
```sh
pip install bw-file-resubmit
```
## Configuration
Add `"file_resubmit"` to `INSTALLED_APPS`:
```py
INSTALLED_APPS = {
...
'file_resubmit',
...
}
```
Setup cache in settings.py:
```py
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
},
"file_resubmit": {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
"LOCATION": '/tmp/file_resubmit/'
},
}
```
## Examples
models.py
```py
from django.db import models
from django.db.models import ImageField
# or if you use sorl-thumbnail:
from sorl.thumbnail.fields import ImageField
class Page(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
image = ImageField(upload_to='whatever1')
```
### Form widgets
#### Ordinary form
forms.py
```py
from django.forms import ModelForm
from file_resubmit.widgets import ResubmitImageWidget, ResubmitFileWidget
from .models import Page
class PageModelForm(forms.ModelForm)
class Meta:
model = MyModel
widgets = {
'picture': ResubmitImageWidget,
'file': ResubmitFileWidget,
}
class Book(forms.Form):
form = PageModelForm
```
#### Admin form
admin.py
**NOTE:** `admin.AdminResubmitFileWidget` has been dropped from `bw-file-resubmit`. If you need to update a legacy `django-file-resubmit` project, use `widgets.ResubmitFileWidget` instead.
```py
from django.forms import ModelForm
from file_resubmit.admin import AdminResubmitImageWidget,
from file_resubmit.widgets import ResubmitFileWidget
from .models import Page
class PageModelForm(forms.ModelForm)
class Meta:
model = MyModel
widgets = {
'picture': AdminResubmitImageWidget,
'file': ResubmitFileWidget,
}
class PageAdmin(admin.ModelAdmin):
form = PageModelForm
admin.site.register(Page, PageAdmin)
```
### Use as a model mixin in admin
admin.py
```py
from django.contrib import admin
from file_resubmit.admin import AdminResubmitMixin
from .models import Page
class PageAdmin(AdminResubmitMixin, admin.ModelAdmin):
pass
admin.site.register(Page, PageAdmin)
```
# Licensing
`bw-file-resubmit` is free software under terms of the MIT License
Raw data
{
"_id": null,
"home_page": "",
"name": "bw-file-resubmit",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "Hugh Rundle <hugh@hughrundle.net>",
"keywords": "django,form,filefield,imagefield,resubmit,cache",
"author": "",
"author_email": "Ilya Shalyapin <ishalyapin@gmail.com>, Hugh Rundle <hugh@hughrundle.net>",
"download_url": "https://files.pythonhosted.org/packages/47/7d/e26848abc7d762897c33d2d39c6c1db60806b6e75fe8e73227f9ee394d0e/bw-file-resubmit-0.6.0rc2.tar.gz",
"platform": null,
"description": "# bw-file-resubmit\n\n**bw-file-resubmit** is a drop-in replacement for [**django-file-resubmit**](https://github.com/un1t/django-file-resubmit), maintained by the BookWyrm project.\n\nIn a Django project you may have forms using `FileField` or `ImageField`. Everything works great, but\nwhen a `ValidationError` is raised, or you want to add some other check before finally submitting the form, you have to reselect all files and images again. This is because HTML `<input type=\"file\">` fields cannot be prepopulated with data due to basic browser security.\n\n**bw-file-resubmit** solves this problem by caching the file and adding it again in the background. It works with `FileField`, `ImageField` and `sorl.thumbnail.ImageField` (see [sorl-thumbnail](https://github.com/jazzband/sorl-thumbnail)).\n\n## How does it work?\n\nSpecial widgets can be used to replace `FileField` and `ImageField`. When you submit files, every widget saves its file to the cache. When a `ValidationError` is raised, the widgets restore files from cache so the user doesn't have to upload them again.\n\n* `ResubmitFileWidget` can be used in place of `ClearableFileInput`\n* `ResubmitImageWidget` can be used in place of `ClearableFileInput`\n* `AdminResubmitImageWidget` can be used in place of `AdminFileWidget` (Django) or `AdminImageWidget` (sorl-thumbnail)\n* `AdminResubmitMixin` will apply the appropriate widget for all `FileField`s and `ImageField`s\n\n## Installation\n\n```sh\npip install bw-file-resubmit\n```\n\n## Configuration\n\nAdd `\"file_resubmit\"` to `INSTALLED_APPS`:\n\n```py\nINSTALLED_APPS = {\n ...\n 'file_resubmit',\n ...\n}\n```\n\nSetup cache in settings.py:\n\n```py\nCACHES = {\n 'default': {\n 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',\n },\n \"file_resubmit\": {\n 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',\n \"LOCATION\": '/tmp/file_resubmit/'\n },\n}\n```\n\n## Examples\n\nmodels.py\n\n```py\nfrom django.db import models\nfrom django.db.models import ImageField\n# or if you use sorl-thumbnail:\nfrom sorl.thumbnail.fields import ImageField\n\nclass Page(models.Model):\n title = models.CharField(max_length=100)\n content = models.TextField()\n image = ImageField(upload_to='whatever1')\n```\n\n### Form widgets\n\n#### Ordinary form\n\nforms.py\n\n```py\nfrom django.forms import ModelForm\nfrom file_resubmit.widgets import ResubmitImageWidget, ResubmitFileWidget\nfrom .models import Page\n\nclass PageModelForm(forms.ModelForm)\n\n class Meta:\n model = MyModel\n widgets = {\n 'picture': ResubmitImageWidget,\n 'file': ResubmitFileWidget,\n }\n\nclass Book(forms.Form):\n form = PageModelForm\n\n```\n\n#### Admin form\n\nadmin.py\n\n**NOTE:** `admin.AdminResubmitFileWidget` has been dropped from `bw-file-resubmit`. If you need to update a legacy `django-file-resubmit` project, use `widgets.ResubmitFileWidget` instead.\n\n```py\nfrom django.forms import ModelForm\nfrom file_resubmit.admin import AdminResubmitImageWidget,\nfrom file_resubmit.widgets import ResubmitFileWidget\nfrom .models import Page\n\nclass PageModelForm(forms.ModelForm)\n\n class Meta:\n model = MyModel\n widgets = {\n 'picture': AdminResubmitImageWidget,\n 'file': ResubmitFileWidget,\n }\n\nclass PageAdmin(admin.ModelAdmin):\n form = PageModelForm\n\nadmin.site.register(Page, PageAdmin)\n```\n\n### Use as a model mixin in admin\n\nadmin.py\n\n```py\nfrom django.contrib import admin\nfrom file_resubmit.admin import AdminResubmitMixin\nfrom .models import Page\n\nclass PageAdmin(AdminResubmitMixin, admin.ModelAdmin):\n pass\n\nadmin.site.register(Page, PageAdmin)\n```\n\n# Licensing\n\n`bw-file-resubmit` is free software under terms of the MIT License\n",
"bugtrack_url": null,
"license": "MIT License",
"summary": "Preserve files in Django forms during form validation errors. Drop-in replacement for django-file-resubmit",
"version": "0.6.0rc2",
"project_urls": {
"Bug Tracker": "https://github.com/bookwyrm-social/bw-file-resubmit/issues",
"Homepage": "https://github.com/bookwyrm-social/bw-file-resubmit"
},
"split_keywords": [
"django",
"form",
"filefield",
"imagefield",
"resubmit",
"cache"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "b7730beb70000c9381f29b773a5f936c77b665b8a3b9d7e68e9efbdd5432004c",
"md5": "3e45ca1d5540bb40fe0c086edbbf2fce",
"sha256": "60689d2d8f66ae53346649e48f5a4c1a90834631042f7ea95f90493b69fbf25f"
},
"downloads": -1,
"filename": "bw_file_resubmit-0.6.0rc2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3e45ca1d5540bb40fe0c086edbbf2fce",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 6507,
"upload_time": "2023-11-05T05:24:34",
"upload_time_iso_8601": "2023-11-05T05:24:34.582976Z",
"url": "https://files.pythonhosted.org/packages/b7/73/0beb70000c9381f29b773a5f936c77b665b8a3b9d7e68e9efbdd5432004c/bw_file_resubmit-0.6.0rc2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "477de26848abc7d762897c33d2d39c6c1db60806b6e75fe8e73227f9ee394d0e",
"md5": "6e3ebe0bef0523bf80fb43fb234d906b",
"sha256": "c1665c44c45309808838ab6068840f22ac59fbc4f8f5c655b015e6d1b253f84c"
},
"downloads": -1,
"filename": "bw-file-resubmit-0.6.0rc2.tar.gz",
"has_sig": false,
"md5_digest": "6e3ebe0bef0523bf80fb43fb234d906b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 7701,
"upload_time": "2023-11-05T05:24:36",
"upload_time_iso_8601": "2023-11-05T05:24:36.457741Z",
"url": "https://files.pythonhosted.org/packages/47/7d/e26848abc7d762897c33d2d39c6c1db60806b6e75fe8e73227f9ee394d0e/bw-file-resubmit-0.6.0rc2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-11-05 05:24:36",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "bookwyrm-social",
"github_project": "bw-file-resubmit",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"tox": true,
"lcname": "bw-file-resubmit"
}