1. 程式人生 > >用Django框架開發一個簡單的企業網站(四)

用Django框架開發一個簡單的企業網站(四)

現在通過後臺可以新建文章分類,並且編輯儲存文章了;由於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
        },
    });
})

清空瀏覽器快取重新整理頁面,現在可以成功上傳圖片了。

後臺功能先做到這裡,後面的文章簡單處理下前臺頁面的資料展現。