用Django框架开发一个简单的企业网站(四)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010815486/article/details/84384283

现在通过后台可以新建文章分类,并且编辑保存文章了;由于Django默认的大容量文本字段是通过一个textarea作为输入方式,所以我们还需要引入一个富文本编辑器,这里我推荐KindEditor(http://kindeditor.net/demo.php),配置简单,功能也齐全。

将下载好的静态文件放在static/路径下,查看需要加载编辑器的默认textarea的id:

可以发现,id为id_字段名,新建一个config.js用于配置编辑器参数:

KindEditor.ready(function(k) {
    window.editor = k.create('#id_content', {
        resizeType: 1,
        allowPreviewEmoticons: false,
        allowImageRemote: false,
        width: '700px',
        height: '400px',
    });
})

然后打开admin.py,写一个配置类:

from django.contrib import admin
from web_app.models import *

class NewsAdmin(admin.ModelAdmin):
    list_display = ('title', 'news_class', 'date', 'show')

    class Media:
        # 在管理后台的相关HTML文件中加入js文件
        js = (
            '/static/kindeditor/kindeditor-all-min.js',
            '/static/kindeditor/lang/zh-CN.js',
            '/static/kindeditor/config.js',
        )

list_display表示需要在后台显示的字段;配置类写好后与相关数据模型一起注册:

admin.site.register(News, NewsAdmin)

后台效果(样式上有些小问题自行修改css文件):

 编辑器自带的上传图片和文件选项还不能使用,我们需要配置一个post上传url;首先在项目settings.py内添加两个配置,设置上传文件目录:

# 上传设置
MEDIA_URL = '/static/upload/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/upload')

在app文件夹内新建一个upload.py处理文件上传:

import os
import uuid
import json
import datetime
from django.http import HttpResponse
from django.conf import settings

# 上传post请求地址
# http://127.0.0.1:8000/upload_file/?dir=media


def upload(request):

    # kindeditor图片上传返回数据格式说明:
    # {'error': 1, 'message': '出错信息'}
    # {'error': 0, 'url': '图片地址'}

    result = {'error': 1, 'message': '上传失败'}
    # input type="file" 中name属性对应的值为imgFile
    files = request.FILES.get('imgFile', None)
    type = request.GET['dir']  # 获取资源类型
    if files:
        result = process_upload(files, type)
    # 结果以json形式返回
    return HttpResponse(json.dumps(result), content_type='application/json')


def is_ext_allowed(type, ext):
    # 根据类型判断是否支持对应的扩展名
    ext_allowed = {}
    ext_allowed['image'] = ['jpg', 'jpeg', 'bmp', 'gif', 'png']
    ext_allowed['flash'] = ['swf', 'flv']
    ext_allowed['media'] = ['swf', 'flv', 'mp3', 'wav', 'wma',
                            'wmv', 'mid', 'avi', 'mpg', 'asf', 'rm', 'rmvb', 'mp4']
    ext_allowed['file'] = ['doc', 'docx', 'xls', 'xlsx', 'ppt',
                           'htm', 'html', 'txt', 'zip', 'rar', 'gz', 'bz2', 'pdf']
    return ext in ext_allowed[type]


def get_relative_file_path():
    # 获取相对路径
    dt = datetime.datetime.today()
    relative_path = '%s/%s/' % (dt.year, dt.month)
    absolute_path = os.path.join(settings.MEDIA_ROOT, relative_path)
    print(absolute_path)
    if not os.path.exists(absolute_path):
        os.makedirs(absolute_path)
    return relative_path


def process_upload(files, type):
    dir_types = ['image', 'flash', 'media', 'file']
    # 判断是否支持对应的类型
    if type not in dir_types:
        return {'error': 1, 'message': '上传类型不支持[必须是image,flash,media,file]'}

    cur_ext = files.name.split('.')[-1]  # 当前上传文件的扩展名
    # 判断是否支持对应的扩展名
    if not is_ext_allowed(type, cur_ext):
        return {'error': 1, 'message': '扩展名不支持 %s类型不支持扩展名%s' % (type, cur_ext)}

    relative_path = get_relative_file_path()
    # linux中一切皆文件
    file_name = str(uuid.uuid1()) + '.' + cur_ext
    base_name = os.path.join(settings.MEDIA_ROOT, relative_path)
    # windows中的路径以\分隔
    file_full_path = os.path.join(base_name, file_name).replace('\\', '/')
    file_url = settings.MEDIA_URL + relative_path + file_name

    with open(file_full_path, 'wb') as f:
        if files.multiple_chunks() == False:  # 判断是否大于2.5M
            f.write(files.file.read())
        else:
            for chunk in files.chunks():
                f.write(chunk)

    return {'error': 0, 'url': file_url}

注意返回的json数据格式不要写错,否则KindEditor编辑器上传会报错。上传的文件我们保存在static/upload目录内,有了上传处理函数后,就可以在app的url.py内配置路由了:

from web_app import upload as u

# app url 配置
urlpatterns = [
    re_path(r'^$', views.index),
    re_path(r'^upload_file/$', u.upload, name='upload'),
]

记得在KindEditor的参数js内(config.js)添加上传url参数:

// 上传请求路径
uploadJson: '/upload_file/',

上传图片测试:

由于Django自带CSRF验证(有兴趣的同学可以了解下:https://www.jianshu.com/p/a178f08d9389),有2种方法解决:

  1. 在settings.py内注释掉'django.middleware.csrf.CsrfViewMiddleware',关闭CSRF验证。
  2. post上传请求头内添加CSRF参数(推荐方法)

贴一个完整的config.js:

KindEditor.ready(function(k) {
    var csrf_token = document.getElementsByName('csrfmiddlewaretoken')[0].value;
    window.editor = k.create('#id_content', {
        resizeType: 1,
        allowPreviewEmoticons: false,
        allowImageRemote: false,
        // 上传请求路径
        uploadJson: '/upload_file/',
        width: '700px',
        height: '400px',
        // 处理csrf验证
        extraFileUploadParams: {
            csrfmiddlewaretoken: csrf_token
        },
    });
})

清空浏览器缓存刷新页面,现在可以成功上传图片了。

后台功能先做到这里,后面的文章简单处理下前台页面的数据展现。

猜你喜欢

转载自blog.csdn.net/u010815486/article/details/84384283