第十八天 實戰(zhàn)練習(5)
今天計劃用Python繼續(xù)一個web開發(fā)的實戰(zhàn)項目練習吵血,學習項目及練習源碼地址:
GitHub源碼
文章內容的編寫與提交
富文本編輯器
我選擇了TinyMCE,原因很簡單,用的人多怜校,而且支持的瀏覽器多,這兩個理由足夠了鸣剪。
雖然中文文檔比較少揩悄,但這個不是重要的,做一個東西弊添,兼容性還是要考慮下的录淡。
使用起步:
首先,需要下載一份copy油坝,
然后:
<script src="/static/tinymce/tinymce.min.js"></script>
其次:將TinyMCE初始化為頁面的一部分
<!DOCTYPE html>
<html>
<head>
<script src='/static/tinymce/tinymce.min.js'></script>
<script>
tinymce.init({
selector: '#mytextarea'
});
</script>
</head>
<body>
<h1>TinyMCE快速開始示例</h1>
<form method="post">
<textarea id="mytextarea">Hello, World!</textarea>
</form>
</body>
</html>
最后:數(shù)據(jù)提交
當form提交時嫉戚,TinyMCE會將內容塞進textarea刨裆,你可以通過正常的post方法獲取到編輯器中的內容,行為與普通textarea完全一致彬檀。
一個內聯(lián)示例:
<div>
<div id="doc-app" style="display: block;">
<div class="toolbar"></div>
<div class="box">
<div class="tit"><input type="text" placeholder="請輸入標題……"></div>
<div class="doc-cnt mce-content-body mce-edit-focus" id="tinydemo-doc" contenteditable="true" spellcheck="false" style="position: relative;"><blockquote><ul><li style="text-align: justify;" data-mce-style="text-align: justify;">在這里輸入文字</li></ul></blockquote></div>
</div>
</div>
</div>
<script>
tinymce.init({
selector: '#tinydemo-doc',
language:'zh_CN',
menubar:false,
inline: true,
plugins: 'print preview searchreplace autolink fullscreen image link media code codesample table charmap hr pagebreak nonbreaking anchor advlist lists textpattern help emoticons autosave bdmap indent2em lineheight formatpainter axupimgs',
toolbar: 'code undo redo restoredraft | cut copy | forecolor backcolor bold italic underline strikethrough link | alignleft aligncenter alignright alignjustify | bullist numlist blockquote subscript superscript removeformat | \
formatselect fontselect fontsizeselect | \
table image media charmap emoticons hr pagebreak print preview | fullscreen | bdmap indent2em lineheight formatpainter axupimgs',
fixed_toolbar_container:'#doc-app .toolbar',
custom_ui_selector: 'body',
//auto_focus: true,
toolbar_drawer: false,
toolbar_sticky: true,
autosave_ask_before_unload: false,
fontsize_formats: '12px 14px 16px 18px 24px 36px 48px 56px 72px',
font_formats: '微軟雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;蘋果蘋方=PingFang SC,Microsoft YaHei,sans-serif;宋體=simsun,serif;仿宋體=FangSong,serif;黑體=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats;知乎配置=BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, WenQuanYi Micro Hei, sans-serif;小米配置=Helvetica Neue,Helvetica,Arial,Microsoft Yahei,Hiragino Sans GB,Heiti SC,WenQuanYi Micro Hei,sans-serif',
images_upload_base_path: '/demo',
images_upload_handler: function (blobInfo, succFun, failFun) {
succFun('/demo/images/img.jpg');
},
init_instance_callback: function(editor){
$('#doc-app').fadeIn(1500);
editor.execCommand('selectAll');
editor.selection.getRng().collapse(false);
editor.focus();
}
});
</script>
圖片上傳
設置初始化參數(shù):images_upload_handler:upload_pic
var upload_pic = function (blobInfo, succFun, failFun) {
var file = blobInfo.blob();//轉化為易于理解的file對象
var formData = new FormData();
formData.append('file', file, file.name );//此處與源文檔不一樣
console.log(formData.get('file')); //FormData私有類對象帆啃,訪問不到,可以通過get判斷值是否傳進去
var config = {
headers: { 'Content-Type': 'multipart/form-data' }
}; //添加請求頭
axios.post('/upload', formData, config)
.then(response => {
console.log(response.data);
succFun(response.data.filename);
})
.catch(error=>{
failFun(error)
})
}
圖片處理服務端示例:
@post('/upload')
async def storefile(request):
try:
reader = await request.multipart()
file = await reader.next()
exts = ['.jpg','.jpeg','.png','.gif','.bpm']
filename = file.filename if file.filename else 'undefined'
suffix = os.path.splitext(filename)
filename = '{}{}'.format(short_uuid(),suffix[1])
filepath = '{}/{}'.format(config.app.uploaddir,filename)
size = 0
with open(filepath, 'wb') as f:
while True:
chunk = await file.read_chunk() # 默認是8192個字節(jié)窍帝。
if not chunk:
break
size += len(chunk)
f.write(chunk)
text = {'res': '上傳成功','filename':'{}{}'.format('/static/uploads/',filename)}
result = text
return result
except Exception as e:
print(e)
result = {'success':False,'error': e}
return result
文件上傳
類似于圖片上傳努潘,這里不再舉例
文檔內容的保存
設置初始化參數(shù):save_onsavecallback: saveConent
前端js代碼:
var saveConent = function (el) {
// do the work on html
var title = $('#b_title').val();
var content = el.getContent()
var data = {
title: title || "",
content: content || ""
}
console.log(data);
axios.post('/b/0',data)
.then(res=>{
console.log(res);
})
.catch(err=>{
console.log(err);
})
}
后端處理:
'''
還沒有作入數(shù)據(jù)庫的處理,這里需要用戶信息坤学,所以需要處理session判定用戶的合法性等
'''
@post('/b/{id}')
async def save_content(*,id,title,content,request):
result = {'success':False}
return result