Django Admin中使用七牛上传文件

公司项目使用七牛云存储文件,而项目控制台基于 Django Admin 开发,现在有个需求要在控制台中直接上传文件到七牛,所以自己就写了一个 Django APP:qiniu_fields 用来实现这个功能。这里记录 & 分享一下。

一、技术方案

Django 本身支持自定义 Model 字段,为了实现需求,我在 URLField 和 TextField 的基础上实现自定义字段,同时重写其对应的 Widget。

二、qiniu_fields APP

具体代码如下:

widgets.py

#! -*- coding: utf-8 -*-
from django import forms
from django.conf import settings
from django.utils.html import smart_urlquote


class QiniuFileWidget(forms.URLInput):
    input_type = 'file'
    template_name = 'file.html'

    def __init__(self, attrs=None):
        final_attrs = {
            'domain': settings.QINIU_DOMAIN,
            'uptoken_url': settings.QINIU_UPTOKEN_URL,
        }
        if attrs is not None:
            final_attrs.update(attrs)
        super(QiniuFileWidget, self).__init__(attrs=final_attrs)

    def get_context(self, name, value, attrs):
        context = super(QiniuFileWidget, self).get_context(name, value, attrs)
        context['current_label'] = '当前:'
        context['widget']['href'] = smart_urlquote(context['widget']['value']) if value else ''
        return context

    @property
    def media(self):
        return forms.Media(js=('qiniu_fields/plupload/plupload.full.min.js', 'qiniu_fields/plupload/i18n/zh_CN.js',
                               'qiniu_fields/qiniu/qiniu.min.js', 'qiniu_fields/qiniu/ui.min.js'))

    # class Media:
    #     js = ('qiniu_fields/plupload/plupload.full.min.js', 'qiniu_fields/plupload/i18n/zh_CN.js',
    #           'qiniu_fields/qiniu/qiniu.min.js', 'qiniu_fields/qiniu/ui.min.js')


class QiniuFileListWidget(forms.Textarea):
    template_name = 'file_list.html'

    def __init__(self, attrs=None):
        final_attrs = {
            'domain': settings.QINIU_DOMAIN,
            'uptoken_url': settings.QINIU_UPTOKEN_URL,
        }
        if attrs is not None:
            final_attrs.update(attrs)
        super(QiniuFileListWidget, self).__init__(attrs=final_attrs)

    @property
    def media(self):
        return forms.Media(js=('qiniu_fields/plupload/plupload.full.min.js', 'qiniu_fields/plupload/i18n/zh_CN.js',
                               'qiniu_fields/qiniu/qiniu.min.js', 'qiniu_fields/qiniu/ui.min.js'))

    # class Media:
    #     js = ('qiniu_fields/plupload/plupload.full.min.js', 'qiniu_fields/plupload/i18n/zh_CN.js',
    #           'qiniu_fields/qiniu/qiniu.min.js', 'qiniu_fields/qiniu/ui.min.js')

forms.py

#! -*- coding: utf-8 -*-
from django import forms

from .widgets import QiniuFileWidget, QiniuFileListWidget


class QiniuFileFormField(forms.URLField):
    prefix = ''
    file_type = 'all'
    widget = QiniuFileWidget

    def __init__(self, *args, **kwargs):
        kwargs["widget"] = QiniuFileWidget(attrs={'prefix': self.prefix, 'file_type': self.file_type})
        super(QiniuFileFormField, self).__init__(*args, **kwargs)

fields.py

#! -*- coding: utf-8 -*-
from django.db import models

from .widgets import QiniuFileWidget, QiniuFileListWidget
from .forms import QiniuFileFormField


class QiniuFileField(models.URLField):
    widget_clz = QiniuFileWidget
    form_field_clz = QiniuFileFormField

    def __init__(self, verbose_name=None, name=None, prefix='', file_type='all', **kwargs):
        self.prefix = prefix
        self.file_type = file_type
        kwargs['max_length'] = 500
        super(QiniuFileField, self).__init__(verbose_name, name, **kwargs)

    def formfield(self, **kwargs):
        self.form_field_clz.prefix = self.prefix
        self.form_field_clz.file_type = self.file_type
        kwargs.update({
            'form_class': self.form_field_clz,
            'widget': self.widget_clz(attrs={'prefix': self.prefix, 'file_type': self.file_type})
        })
        return super(QiniuFileField, self).formfield(**kwargs)


class QiniuFileListField(models.TextField):

    def __init__(self, *args, prefix='', file_type='all', **kwargs):
        self.prefix = prefix
        self.file_type = file_type
        super(QiniuFileListField, self).__init__(*args, **kwargs)

    def formfield(self, **kwargs):
        kwargs.update({
            'widget': QiniuFileListWidget(attrs={'prefix': self.prefix, 'file_type': self.file_type}),
        })
        return super(QiniuFileListField, self).formfield(**kwargs)

三、项目Demo

Django Qiniu Fields代码和 Demo 项目见Github: django-qiniu-fields

Over!


用户评论
开源开发学习小组列表