Django之自定义Field实现admin直接上传图片到七牛云并存储链接
Django自带的admin模块的功能实际上已经足够强大了,但是我们不免有一些自定义化的需求,比如我们在后台存储图片时,为了提高系统的性能,我们会使用第三方cdn服务去存储图片等静态资源,然后将链接存入数据库中,但是将图片上传到cdn,然后复制链接存入数据库又是比较繁琐的一个过程,作为程序员,肯定要寻求更高效的解决方法,比如自定义Field。 实际上覆盖admin的字段在Django中有两种方式,一种是自定义Form,然后在admin.py对应的ModelAdmin中覆盖form属性,比如: class MyForm(forms.Form): class Meta: widgets = { 'field':CustomWidget() } # admin.py class MyAdmin(admin.ModelAdmin): form = MyForm 这样就将field字段覆盖为CustomWidget,在CustomWidget中,就可以自定义template和css等。这样的话在每个需要自定义的Field都需要这样做一次,如果使用频繁的话就不怎么推荐,推荐另一种更通用的方式,自定义models.py中的Field。 1、构建widgets 要实现上传七牛的功能,首先在项目同名的目录下建一个widgets.py,实现自己的QiniuWidgets类,另外说一点的是,该实现参考了django-ckeditor项目,可以在admin中集成富文本编辑器,还是很不错的,推荐使用。 class QiniuWidgets(forms.FileInput): template_name = 'admin/qiniu_input.html' def __init__(self, attrs=None, app=None, table=None, unique_list=None): """ :param attrs: :param app: app :param table: 数据模型 :param unique_list: 唯一标识列表,除了id """ super(QiniuWidgets, self).__init__(attrs) self.unique = unique_list if settings.DEBUG: env = 'dev' else: env = 'pro' self.filename_prefix = '{}/{}/{}/'.format(env, app, table) def format_value(self, value): return value def value_from_datadict(self, data, files, name): file = files.get(name) # type:InMemoryUploadedFile file_data = b''.join(chunk for chunk in file.chunks()) # 取出二进制数据 file_type = file.name.split('.')[-1] # 得到文件的后缀 unique_filename = '_'.join(list(map(lambda x: data.get(x), self.unique))) file_name = self.filename_prefix + '{}_{}.{}'.format(name, unique_filename, file_type) # 构造文件的唯一文件名 q = QiniuUtils(settings.QINIU_ACCESS_KEY, settings.QINIU_SECRET_KEY) # 七牛上传实例 q.delete(settings.QINIU_BUCKET_NAME, file_name) # 删除已经存在的 q.upload(settings.QINIU_BUCKET_NAME, file_name, file_data) # 上传新的 http = 'https://' if settings.QINIU_USE_SSL else 'http://' url = http + settings.QINIU_DOMAIN + '/' + file_name # 拼接最终的url return url def render(self, name, value, attrs=None, renderer=None): context = self.get_context(name, value, attrs) template = loader.get_template(self.template_name).render(context) return mark_safe(template) 现在QiniuWidgets介绍类中方法的含义: ...