I'm looking for some pointers to implementing a file upload progress bar that gives feedback about the current status of the upload of a FileField inside a ModelForm.
My ModelForm has got a lot of fields (not only FileField) and I would like to show a live feedback of the progress with a progress bar.
Thanks.
Here is my solution to the problem: django-smartfields, this app can take care of reporting progress, convert images or videos, clean up old files and more. It has some requirements for progress reporting:
- django-crispy-forms
- jQuery
- plupload
- bootstrap3
- bootbox
I am working on documentation for django-smartfields right now, but this portion of the app is still not documented, but here is how you would use it.
from django.db import models
from django.conf import settings
from smartfields import fields
class FileModel(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, editable=False)
file = fields.FileField(uploadTo='files')
# other fields ....
parent_field_name = 'user'
def has_upload_permission(self, user, field_name=None):
return user == self.user
Now in forms.py
:
from django import forms
from myapp.models import FileModel
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout
from smartfields.crispy.layout import FileField
class FileForm(forms.ModelForm):
class Meta:
model = FileModel
fields = ('file', other fields...)
@property
def file_upload_url(self):
return reverse("smartfields:upload", kwargs={
'app_label': 'test_app',
'model': FileModel.__name__,
'field_name': 'file',
'pk': self.instance.pk,
'parent_field_name': 'user'
'parent_pk': self.instance.user.pk
})
def __init__(self, *args, **kwargs):
super(FileForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_tag = False
self.helper.layout = Layout(
FileField('file', plupload_options={
'url': self.file_upload_url,
'filters': {
'max_file_size': "20mb",
'mime_types': [{'title': "Documents",
'extensions': "pdf,doc"}]
}}))
Nothing special needs to be done in the views.py, except that 'file_form'
should be in the context. Make sure smartfields
are in INSTALLED_APPS
and urls
have url(r'^smartfields/', include('smartfields.urls', namespace='smartfields')),
in them or you can create a customized upload view, by extending smartfields.views.FielUpload
.
In the template:
{% load static crispy_forms_tags %}
<link rel="stylesheet" href="{% static 'bootstrap3/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'bootstrap3/css/bootstrap-theme.min.css' %}">
<link rel="stylesheet" href="{% static 'css/smartfields.css' %}">
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type="text/javascript" src="{% static 'bootstrap3/js/bootstrap.min.js' %}"></script>
<script type="text/javascript" src="{% static 'plupload/js/plupload.full.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/bootbox.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/smartfields.js' %}"></script>
<form method="POST">
{% crispy file_form %}
<input class="btn btn-default" type="submit" name="btn_save" value="Save">
</form>
Let me know if you have any questions or if it doesn't work for some reason. Make sure you use version from github, javascript file on pypi is outdated.