野外泛在线考核系统(十二)
三、电脑端+平板
接着(十一)开始研究Django webSocket的问题,最开始参考django websocket。而后经作者推荐,下载了这里的代码,进行了研究,结果问题就开始了
(七)Django webSocket 或者 http 通信
问题1: django使用channels实现webSocket启动失败
参考作者提供的方法,将channels的版本降到3.0.1
- 安装指定版本的channels:
sudo pip install channels==3.0.1
- 启动服务解决问题了Django.core.exceptions.inproperyConfigured:无法导入ASGI_应用程序模块’项目.路由’,于是参考作者将channels的版本再次降为1.1.8 结果又出现一堆问题,于是又把channel的版本改为3.0.1,结果,居然前面的错误没有了。
- 研究发现webSocket并不适合我的项目,应为我这个并不需要实时通信,只要能通信即可,而且发送的数据也不多,完全可以用http通信解决。
平板端
- 主要参考了<HarmonyOS第一课>从网络获取数据的新闻数据加载的例子
- 核心是通过向服务端发送请求,获取JSON格式的数据。
- 在HttpUtil.ets中:
Logger.info 用来监测是否倒底是哪里的问题,这里很容易出错,有JSON格式的问题,也有路径不对的问题,都要通过监测来发现。很多的坑都是自己不注意,复制代码,要么是格式错误,要么是路径不对。
import http from '@ohos.net.http';
import ResponseResult from '../bean/ResponseResult';
import { CommonConstants as Const, ContentType } from '../constants/CommonConstants';
import Logger from '../utils/Logger';
export function httpRequestGet(url: string): Promise<ResponseResult> {
Logger.info('check-code:1',url);
let httpRequest = http.createHttp();
let responseResult = httpRequest.request(url, {
method: http.RequestMethod.GET,
readTimeout: Const.HTTP_READ_TIMEOUT,
header: {
'Content-Type': ContentType.JSON
},
connectTimeout: Const.HTTP_READ_TIMEOUT,
extraData: {}
});
let serverData: ResponseResult = new ResponseResult();
// Processes the data and returns.
return responseResult.then((value: http.HttpResponse) => {
Logger.info('check-code:2',value.responseCode.toString());
if (value.responseCode === Const.HTTP_CODE_200) {
// Obtains the returned data.
let result = `${value.result}`;
Logger.info('check- http:','访问成功');
Logger.info('check- http:',result);
let resultJson: ResponseResult = JSON.parse(result);
Logger.info('check- http:','转换数据');
if (resultJson.code === Const.SERVER_CODE_SUCCESS) {
serverData.data = resultJson.data;
Logger.info('check- http:','获得数据');
Logger.info('check- http:',serverData.data.toString());
}
serverData.data = resultJson.data;
serverData.code = resultJson.code;
serverData.msg = resultJson.msg;
} else {
Logger.info('check- http:','访问失败');
serverData.msg = `${$r('app.string.http_error_message')}&${value.responseCode}`;
}
return serverData;
}).catch(() => {
Logger.info('check http:','访问异常');
serverData.msg = $r('app.string.http_error_message');
return serverData;
})
}
- DataViewModel.ets
getDataList方法是获取数据, setDataList方法是发送数据(id,score)
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* limitations under the License.
*/
import { CommonConstants as Const } from '../common/constants/CommonConstants';
import {ContentScoreData,ItemScore }from '../common/bean/ScoreData';
import { httpRequestGet } from '../common/utils/HttpUtil';
import Logger from '../common/utils/Logger';
import ResponseResult from '../common/bean/ResponseResult';
class DataViewModel {
/**
* 获取数据列表从服务器 *
* @return ContentScore[] DataList
*/
getDataList(path: string , teacherID: string): Promise<ContentScoreData[]> {
return new Promise(async (resolve: Function, reject: Function) => {
let url = `${Const.SERVER}/${path}`;
url += '/' + teacherID;
httpRequestGet(url).then((data: ResponseResult) => {
Logger.info('check- data:',data.code);
if (data.code === Const.SERVER_CODE_SUCCESS) {
Logger.info('check- data:','解析数据');
resolve(data.data);
Logger.info('check- data:',data.data.toString());
Logger.info('check- data:','解析成功');
} else {
Logger.error('getNewsList failed', JSON.stringify(data));
reject($r('app.string.page_none_msg'));
}
}).catch((err: Error) => {
Logger.error('getNewsList failed', JSON.stringify(err));
reject($r('app.string.http_error_message'));
});
});
}
setDataList(path: string ,id:number, score: number): Promise<ContentScoreData[]> {
return new Promise(async (resolve: Function, reject: Function) => {
let url = `${Const.SERVER}/${path}`;
url += '/' + id + '/' + score;
httpRequestGet(url).then((data: ResponseResult) => {
Logger.info('check- data.code:',data.code);
if (data.code === Const.SERVER_CODE_SUCCESS) {
Logger.info('check- data:','解析数据');
resolve(data.data);
Logger.info('check- data:',data.data.toString());
Logger.info('check- data:','解析成功');
} else {
Logger.error('getNewsList failed', JSON.stringify(data));
reject($r('app.string.page_none_msg'));
}
}).catch((err: Error) => {
Logger.error('getNewsList failed', JSON.stringify(err));
reject($r('app.string.http_error_message'));
});
});
}
}
let dataViewModel = new DataViewModel();
export default dataViewModel as DataViewModel;
- 在ManageData.ets中调用
获取数据data ,写入this.contentScores 中
changeCategory() {
DataViewModel.getDataList(this.seachPath, this.teacherID).then((data: ContentScoreData[]) => {
this.contentScores = data;
}).catch((err: string | Resource) => {
promptAction.showToast({
message: err,
duration: CommonConstants.ANIMATION_DURATION
});
});
}
- 将获取的数据写入平板的数据库中:
insertDataToTable():void{
for(let score of this.contentScores){
this.ContentScoreTable.insertData(score, (id: number) => {
});
}
}
- 通过ResponseResult.ets 规定服务器和平板之间传输JSON数据的格式
code 是双方规定的暗号,msg 是传输附带的消息,data才是真正要传输的数据
export default class ResponseResult {
/**
* Code returned by the network request: success, fail.
*/
code: string;
/**
* Message returned by the network request.
*/
msg: string | Resource;
/**
* Data returned by the network request.
*/
data: string | Object | ArrayBuffer;
constructor() {
this.code = '';
this.msg = '';
this.data = '';
}
}
电脑端
- 首先在Lesson/views.py中:
# Lesson/views.py
def search_contentScore(request,teacherID):
#contents = ContentScore.objects.filter(teacher__teacherName = name).values()
teacher = Teacher.objects.filter(teacherID=teacherID).first()
print(teacher.teacherName)
name = str(teacher.teacherName)
contents = ContentScore.objects.filter(teacher__teacherName=name)
r = []
for c in contents:
r.append({'id':str(c.id),'content':str(c.content),'item':str(c.item),'team':str(c.team),'teacher':str(c.teacher),'contentScore':str(c.contentScore),'contentDate':str(c.contentDate)})
#print(res1)
res = list(r)
#print(res)
data = {'code': 'success', 'msg': '', 'data':res }
print(data)
return JsonResponse(data,json_dumps_params ={"ensure_ascii":False},safe=False)
def update_contentScore(request,id,contentScore):
res = 'id='+str(id)+':'+'contentScore='+str(contentScore)
print('更新数据成功'+ res)
# cc = ContentScore.objects.filter(id=id)
ContentScore.objects.filter(id=id).update(contentScore=contentScore)
data = {'code': 'success', 'msg': '更新数据contentScore: '+contentScore+' 成功'}
return JsonResponse(data, json_dumps_params={"ensure_ascii": False}, safe=False)
- Lesson/urls.py:
# 带参数传递数据
path('search_contentScore/<teacherID>', views.search_contentScore, name='search_contentScore'),
# 更新数据
path('update_contentScore/<id>/<contentScore>', views.update_contentScore, name='update_contentScore'),
- 通过上述设置,平板首先从发送请求,从电脑的Django数据表中获取数据,并写入平板数据库中,而后读取在平板显示,评分,再次写入平板数据库,最后读取更改过的数据发送至电脑端更新Django数据库中的数据。