Django - admin 表单编辑页面,增加自定义功能,前端上传视频到oss

# 背景:可以在admin编辑页面原有基础上,增加一些可定制的功能,如:在本地上传图片到oss,减少服务器的带宽压力,下面就以此为例。

示例图:

 

 

一。models.py

# video 可以直接用字符串存储,因为最终里面只有有一串oss的视频路径

class News(models.Model):
    OSS_URL = 'https://xxxx.aliyuncs.com'
video = models.FileField(verbose_name="视频", upload_to="news/video")

 

二。admin.py

@admin.register(News)
class NewsAdmin(admin.ModelAdmin):
    list_display = ('id', 'video')

    # 覆盖内置的编辑页面,增加自定义页面(继承原有页面的所有内容,并增加自定义内容)
    # 该页面存放在 /templates/admin/ 目录下
    change_form_template = 'admin/addfile.html'

    def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):

        # 可设置字段,通过模板语言显示到 addfile.html 页面中
        context['accessKeyId'] = '111'
        context['accessKeySecret'] = '222'

        if obj and obj.video:
            context['video_url'] = News.OSS_URL+obj.video.url
        return super(ZhongYeGuanZhuAdmin, self).render_change_form(request, context, add, change, form_url, obj)

    def save_model(self, request, obj, form, change):
        # 拿到前端返回的oss视频地址, 并存入数据库
        video = request.POST.get('video')
        if video:
            obj.video = video
        super().save_model(request, obj, form, change)

 

三。addfile.html

# 1. 页面继承了原有编辑面的内容,并加入了自己的代码进去

# 2. 请注意页面引入了 layui.css,layui.js,aliyun-oss-sdk.js,format.js 多个库

# 3. 请注意页面中的 js 代码需要引入 django.jQuery 才会生效

<link rel="stylesheet" href="xxx.aliyuncs.com/layui/css/layui.css" media="all">

{% extends 'admin/change_form.html' %}
{% load static %}

{% block admin_change_form_document_ready %}
{{ block.super }}

<style>
    #up_{
        margin-left: 30px;
        display: inline-block;
        width: 60px; height: 30px;
        text-align: center; line-height: 30px;
        background: green;
        color: #fff !important;
    }
</style>

<script src="http://xxx.aliyuncs.com/layui/layui.js"></script>
<script src="https://xxx.aliyuncs.com/js/aliyun-oss-sdk-6.16.0.min.js"></script>
<script src="http://xxx.aliyuncs.com/js/date.format.js"></script>

<script>

(function($) {
{% if video_url %} $('.field-video .file-upload a')[0].href = '{{ video_url }}'; {% endif %} $("#id_video").before('<input type="hidden" name="video" id="video">'); $("#id_video").after('<a href="javascript:;" id="up_">上传视频</a>'); var loading; async function upload_to_oss(file_, mulu){ // 设置加载 loading = layer.load(2, { shade: 0.4 }); let client = new OSS({ region: "oss-cn-beijing", accessKeyId: "{{ accessKeyId }}", accessKeySecret: "{{ accessKeySecret }}", stsToken: "", bucket: "testz", }); // 将文件上传oss const options = { // 获取分片上传进度、断点和返回值。 progress: (p, cpt, res) => { console.log(p); }, // 设置并发上传的分片数量。 parallel: 4, // 设置分片大小。默认值为1 MB,最小值为100 KB。 partSize: 1024 * 1024, // headers, // 自定义元数据,通过HeadObject接口可以获取Object的元数据。 meta: { year: 2024 }, mime: "text/plain", } let lujing = mulu + Date.now()+'-'+file_.name; try { // 分片上传。 const res = await client.multipartUpload('/media'+lujing, file_, { ...options, }); return {'file_name': lujing} } catch (err) { console.log(err); layer.close(loading); return {'error': '上传失败, 请稍后再试'} } } $("#up_").click(async function () { let id_video = $("#id_video")[0].files; console.log('id_video >', id_video) if(id_video.length <= 0){ layer.msg('请选择视频文件'); return false; } let file = id_video[0]; console.log('file >', file) await upload_to_oss(file, '/{{ upload_to }}/').then(function (data) { layer.close(loading); if(data.error){ layer.msg(data.error); return false; } let f_name = data.file_name; $("#video").val(f_name); layer.msg('上传成功'); }); }) })(django.jQuery); </script> {% endblock %}

 

posted @ 2024-01-29 19:52  _Q  阅读(81)  评论(0编辑  收藏  举报