Интеграция plupload в django

Как быть, если необходимо загрузить на сервер несколько файлов? В django есть fieldset, но они настолько рогаты, что пользоваться ими невозможно. Поэтому мы пойдем другим путем.

Для аплоада файлов решил воспользоваться plupload. Посмотрим что же это такое.

The developers of TinyMCE brings you Plupload, a highly usable upload handler for your Content Management Systems or similar. Plupload is currently separated into a Core API and a jQuery upload queue widget this enables you to either use it out of the box or write your own custom implementation.

Звучит неплохо, поэтому приступаем к хакингу. Для начала подготовим простую платформу для удобного аплоада через внутренний механизм django.

*PLACEHOLDERS_PRE_2*

Как видно я не использую ManyToManyField для модели Article, это было бы излишне. Вместо этого используем связь OneToMany.

Создадим форму для аплоада.

forms.py
class PhotoForm(forms.ModelForm):
    class Meta:
        model = Photo
        exclude = ('article', )

Я исключил из формы поле article, оно не понадобится на этапе сохранения формы, зададим его чуть позже, когда будет инстанс класса Photo.

Определяем нашу модель в админ-части.

admin.py

class PhotoAdmin(admin.ModelAdmin):
    
    list_display = ((lambda x: x.article.title), 'file', )
    
    
class ArticleAdmin(admin.ModelAdmin):
    
    list_display = ('title', )
    change_form_template = 'article_change_form.html'
    
    class Media:
        js = (
              settings.MEDIA_URL+'plupload/plupload.full.js',
              '%splupload/jquery.plupload.queue/jquery.plupload.queue.js' % (
                    settings.MEDIA_URL),
        )
        css = {"all": (
            '%splupload/jquery.plupload.queue/css/jquery.plupload.queue.css' % (
                settings.MEDIA_URL),)
        }
    
    
admin.site.register(Photo, PhotoAdmin)
admin.site.register(Article, ArticleAdmin)

В админ-части джанго очень сложно что-то кастомизировать, и постараться лучше этого вообще не делать, но раз нам надо добавить поле, которое не привязано к модели Article, плюс написать кучу дополнительного кода для инициализации виджета аплоадера, то наверно лучшим способом будет переопределить шаблон формы, унаследовать его от «admin/change_form.html», переопределить необходимые блоки, не забыть при этого сделать вызов {{ block.super }}.

И использовать документацию Plupload для конечной интеграции. Поехали.

article_change_form.html

{% extends "admin/change_form.html" %}

{% block extrahead %}
{% if change %}
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">google.load("jquery", "1.4");</script>

<script type="text/javascript">// Convert divs to queue widgets when the DOM is ready
    $( function() {
        $("#uploader").pluploadQueue({
            // General
            runtimes : 'flash',
            url : '{% url upload-file object_id %}',
            max_file_size : '10mb',
            chunk_size : '1mb',
            unique_names : true,

            // Resize images on clientside if we can
            resize : {
                width : 320,
                height : 240,
                quality : 90
            },

            // Specify what files to browse for
            filters : [{
                title : "Image files",
                extensions : "jpg,gif,png"
            },
            ],

            // Flash settings
            flash_swf_url : '{{ MEDIA_URL }}plupload/plupload.flash.swf',
        });

        // Client side form validation
        $('form').submit( function(e) {
            var uploader = $('#uploader').pluploadQueue();

            // Validate number of uploaded files
            if (uploader.total.uploaded == 0) {
                // Files in queue upload them first
                if (uploader.files.length > 0) {
                    // When all files are uploaded submit form
                    uploader.bind('UploadProgress', function() {
                        if (uploader.total.uploaded == uploader.files.length)
                            $('form').submit();
                    });
                    uploader.start();
                } else
                    $('form').submit();

                e.preventDefault();
            }
        });
    });</script>
{% endif %}{{ block.super }}
{% endblock %}

Теперь осталось реализовать только метод загрузки.

*PLACEHOLDERS_PRE_6*

Что мне не удалось это заставить работать через html5, обидно, но и флеш неплохо справляется.

Рабочие исходники лежат на гитхабе.

Напоследок скриншот с внедренным plupload.

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

👍НравитсяПонравилось0
В избранноеВ избранном0
Подписаться на автора
LinkedIn



Підписуйтесь: Soundcloud | Google Podcast | YouTube


10 комментариев

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

Щиро Вам дякую за даний how-to

А редактирование как работает?

Если используется админка, то почему не использовать admin.TabularInline? Или вся проблема в fieldset-ах? Если да, то не могли бы указать на недостатки при его использовании...

TabularInline ограничен количеством полей, да и выбирать каждый раз файл по одному проигрышный вариант против выбора нескольких файлов скопом. Вам так не кажется?

Ограничение количества полей не должно быть проблемой, т.к. можно указать какие поля отображать. А вот выбирать каждый файл по отдельности — это да неудобно. Но мне кажется можно доработать скрипт с функцией выбора нескольких файлов и в соответсвии с выбраным количеством расширить количество записей в TabularInline.

Ограничение количества полей не должно быть проблемой, т.к. можно указать какие поля отображать.

Прошу прощения, я неправильно выразился, TabularInline ограничивает количество рядов отображаемых за раз.

Прошу прощения, я неправильно выразился, TabularInline ограничивает количество рядов отображаемых за раз.

Вы про количество отображаемых форм?

Так есть параметр extra, в котором указываете сколько форм отображать и можете создать столько рядов, сколько вам нужно.

Больше похоже на то, как использовать plupload, а не как улучшить ним админку. Что если кроме файла нужно заполнять дополнительные поля для фотографии? И как редактировать/удалять фотографии?

Так есть параметр extra, в котором указываете сколько форм отображать и можете создать столько рядов, сколько вам нужно.

представьте ситуацию, когда нужно загрузить более ста файлов. TabularInline не спасет пользователя от нудной работы каждый раз выбирать файл. об этом в комментариях уже говорили.

Больше похоже на то, как использовать plupload, а не как улучшить ним админку.

тема поста не как улучшить админку, а как встроить plupload, скажем это отправная точка, маленький how-to.

Что если кроме файла нужно заполнять дополнительные поля для фотографии? И как редактировать/удалять фотографии?

я не ставил перед собой цели описать как реализовать редактирование удаление. простите. :-)

Подписаться на комментарии