python中2.0 2_python2.0_day22_web聊天室二

上节内容已经实现了客户端使用长轮询的方式获取消息的功能.

但是还没有展现到前端.本节内容将实现

1.展现消息到前端窗口.

2.客户端之间发送图片和文件.

3.文件上传时显示进度条

下面我们来实现上面3个功能.

1.展现消息到前端窗口.在展示前我们要解决一个问题.

问题1:我们先看看前端现在虽说能点击左边好友列表,发送消息给选择的好友,但是右边的消息窗口却一直不变.

如下.我给大神发一个111, 显示在这个window窗口,我在给小雨发一个 还是显示在这个窗口.这个肯定是不对的.应该实现得像webQQ和微信一样.点击到指定好友时,只显示和这个好友的消息纪录.

引入

那么我们先来解决这个问题

后端实现思路: 1.将所有的消息存到数据库里,切换到指定用户的时候,从数据库里把消息展示出来.这种方式是后台做的.对于聊天好像不太实用,占用空间.

前端实现思路: 1.为每一个好友创建一个消息窗口的div,默认都是hide隐藏.当选择指定的好友时,removeClass(hide)即可.这种方式可以,实现起来也不难.

2.使用jquery中的data.每一个元素有一个data属性,可以给data属性设置值也可以取 data属性的值.如图

引入

这种方式可以使用.老师觉得这个data属性有些鸡肋!为什么说是鸡肋呢?因为你都用了jquery了,使用给消息窗口这个div元素设置data属性.存储 用户id:聊天内容 ,这个和创建一个字典没有任何区别.

3. 在js中创建一个全局字典.存储 消息类型:用户id:聊天内容 ,切换不同好友的时候,先把现有的消息内容dump到字典,然后loads 新好友的内容.

我们就采用前端实现思路的第3种方式. 在js中创建一个字典.

那么问题来了,从哪里入手.

当然从请求源开始.点击切换用户的函数.

我们看这个函数要做哪些?如图

功能是要实现如上图,但是顺序要调整下.我们应该在更改title之前把消息存起来.所以合理的函数应该是下面这样的.

结构理清楚了.开始实现.

现写一个全局字典,字典写到哪里都行.这里我们就写在$(document).ready(function{}) 的上面,如图:

接下来先把老的信息存到这个全局字典.新的消息取出来.

代码实现如图:

这时候我们来访问测试下:

这样我们就解决了问题1了.下面我们就把接收到的消息展示在前端

首先看下现在收到消息的处理方法:

function GetNewMsgs(){

$.getJSON("{% url 'get_new_msgs' %}",function(callback){

console.log(callback);

GetNewMsgs();

});

}

只是打印.现在前端看下:

所以我们展示数据要有以下几步:

1.遍历上图中array[3]这个数组

2.分析每一个object里的from

3.判断如果from消息来源是我正在聊的对象也就是chat-box-window正在打开的对象,就把消息append到chat-box-window的html中

如果不是正在打开的聊天对象,那么就把消息append到全局字典消息from来源的ID下.

4.在消息展示之前还要把每一个object拼接成html的代码.

就是把饭回来的object 字典,整理成html代码

鉴于把object字典整理成html代码,需要一定的代码量,那我们就把这个写成一个函数.叫做ParseNewMsgs(),于是GetNewMsgs()函数如下:

上图说是for循环字典,其实不是的,这里后端返回来的是一个object的列表.for循环列表时取到的是下表

我们这里要温故下html中for循环的知识了.自己看

最终代码如下

然后前端接收信息看下结果如图:

接下来就是把拼接html.

我们先处理正在聊天对象发过来的消息拼接.代码如图:

我们先来测试下:

我们看上图聊天已经展示到消息窗口了,但还存在上图所述问题.

除了上面的问题,你如果是在windows下进行测试,会经常出现一方发给另外一方能收到,而另外一方发给你收不到.

查看后台你会发现一个规律,页面刷新一次,然后在发送消息,后台就会有断开报错.报错原因就是socket断开了,你在发送消息.

这个原因可能是windows,具体不详.记住就好.在Linux下没有这种问题.

我们来看看前端代码改的两处.

下面我们来拼接处理,不是正在聊的对象,如何把消息存储在全局字典里.

我们测试看下结果:

首先大神的账户和小雨聊.这时候说明大神聊天的对象不是"测试账户",如图

在用测试账户给大神发信息如图:

这时候大神的账户把聊天对象切换到测试账户,看看能不能收到消息,如图

我们看成功了.那么我们还要实现一个功能,就是显示新消息的个数.如图:

实现思路:

14

{{friend.name}}

我们可以把 14 默认添加hide隐藏样式,另外把缺省14改成0.

我们找到了元素,记得是元素,不是docment对象,所以不能是使用jquery的方法.要把找到的元素变成docment对象,之前我们用过就是加上$()即可

于是我们可以这样实现:

你可能会问既然元素都找到了,为啥还要转换成docment类呢?

因为我们要用的不是这个li元素 ,而是li元素下的span元素,我们要对这个元素进行更改.

我们总结下:

var li_ele = $(".list-group li[contact-type='single']").filter("li[contact-id='3']")[0]

$(li_ele).find(".badge")

我们接下来就是对这找到的内容进行操作.

接下来我们发送测试看看效果.

至此消息数量的提示已经完成.但是当我们切换有消息的好友的时候,是不是应该把消息数从新改成 hide并且数量改成0.

因此我们应该修改OpenChatWindow()函数来实现

接下来测试如下:

至此单对单的聊天的几本功能实现了,下面我们来实现下群组聊天是该如何实现?

群组聊天和单人聊天有什么不一样.

后台,处理后发给群里所有人

前端,收消息时前端展示时逻辑有些不一样

我们1对1 时,消息展示在好友处是根据后台返回的object 字典里的from id取到的.

而群组我们就不能根据from id来取了.而是根据to 的id来取到群组的id,from只是发消息的人.

因此我们改动两处,1,是sendmsg调用的后台视图函数send_msg.

2.是前端获取消息里的消息拼接处理方法

function GetNewMsgs(){

$.getJSON("{% url 'get_new_msgs' %}",function(callback){

console.log(callback);

ParseNewMsgs(callback); //重点是要改这个函数

GetNewMsgs();

});

}

我们先来修改后台的视图函数,我们先看看现在send_msg视图函数是怎么处理消息的.

我们把视图函数修改成如下:

后端的视图函数就做这些修改.

接下来就是前端取数据了.

前端取数据需要注意的就是 消息object里的key to是消息展示的位置.from只是显示在群租聊天框的人员姓名.

我们先看下目前的消息处理函数

于是把前端函数改成如下:

下面我们进行测试

至此分组聊天的功能我们已经实现了.

但是有一个问题我们要解决,就是在消息框中显示的发消息的人是ID而不是人员名称。这里要改成人员名称。

简单,我们可以在发送消息时,消息字典里加入发送人员的from_name属性。

如下:

然后,前端在拼接消息时也修改如下:

上面的问题解决了,几本是可以聊天了,但是实际测试下 来感觉会丢失消息,原因可能是socket的也可能是长轮询的方式有点问题,具体没有深入研究。

先不管,我们在来实现一个功能,文件上传.

思路: 上传用post 用ajax .后台处理的URL和和处理消息的URL是同一个。为什么可以是同一个。因为对于用户来说都是发送消息。

那么我们就要修改后台处理get_msgs()函数了。判断前端传来的是图片还是文本信息。如果是文本就不用说了,存到队列中。

如果是图片那么就把图片的url存到信息中。为了好判断是图片还是文本,我们就在object消息字典中再加一个key,来表示发送消息到底是什么类型。

那么我们开始动手,顺序依然是从请求源开始。 触发这个上传文件请求的是哪里。是在消息页面中。我们想图片就不在消息里写入了。我们在emoj处写一个文件上传的前端代码。

如图:

代码如下:

显示的样式很不好看,如下:

看到小图标的样式了把,但是上面加了input的样子很丑,jquery里肯定有具有input type="file"的代码,并且好看点的。

我们稍微调整下,让它不那么难看,然后在实现功能。

然后在看看样子:

然后把上面代码加上onclock事件

接下来我们就来写 FileUpload()函数,写之前我们来会想下:

我们在bbs系统里上传图片用的form表单。form表单会有一个问题,就是上传成功后会刷新页面。

这里我们当然不希望它刷新页面了。那么应该怎么办?就是不用form表单二用ajax异步提交文件。

什么是ajax异步提交文件。之前ajax不支持提交文件。那时候采用在页面用一个afreem,就是在页面里搞一个其他页面框架,内连东西。这个内连框架和服务器端保持长连接,总之浪费资源又恶心。

但是现在jquery的ajax支持异步传输文件了。

我们就把下面这段代码作为,ajax异步上传文件的范例记住。不会就来找把。

在写之前,我们来回忆下,之前在使用form上传文件时,前端form又两点需要注意的:1.必须是post形式才能上传文件 2。必须又一个enctype="multipart/form-data" 才能进行文件上传。

如图:

同样我们用ajax上传是不是也要又这两个限制条件?是的,顺便我们来说明下ajax如何实现异步文件上传的。

首先我们知道form是可以上传文件的。那么ajax实现文件上传的思路就是,在js中实例化一个form对象,把相关数据都塞进这个form实例中。

然后在通过ajax把这个form对象传到服务器上。

于是范例代码如下:

看看上图,思路是不是清晰了很多

下面我们来看看到底塞进formdata实例中的是什么东西。

首先要知道 $("#file_test")其实查找的是input type="file"这个标签。所以我们先给之前代码的input加一个id="file_upload"

然后访问,打印下看看到底是个什么东西,

就是把上面的对象给放到formdata实例里。

上图内容要仔细看了。对于理解后面的操作有帮助。

我们在看下ajax异步上传文件代码中有一句需要理解的:

而上面我们提到的form表单提交后台的两个条件。就是通过下图中的两处实现的。你就记住这是必须加的

最终前端ajax上传文件的代码如下:

function UploadFile(){

var formDate = new FormData();

console.log($("#file_upload")[0].files[0]);

formDate.append('file',$('#file_upload')[0].files[0]);

$.ajax({

url: "{% url 'file_upload' %}",

type: 'POST',

data : formDate,

processDate: false, //tell jQuery not to process the data

// 默认提交的post或者get请求会把后面的参数压缩成url参数专用的urlinto的格式,然后发送给后台。

// 但是我们这里发送的是文件,所以就上面的设置就告诉浏览器不用压缩了

contentType: false, //tell jQuery not to set contentType

// 不要加什么请求头,说白了就是原来是什么样就是什么样,不要给formDate加其他内容了。

success: function(data){

console.log(data);

//alert(data);

}

});

}

这个时候你就通过ajax提交了,提交后后台如何处理呢?必定它和form 提交的方式不一样。

下面是不是该修改URL了, 请求源 -> url -> 视图函数 -> 前端html

urlpatterns = [

# url(r'^$/', views.acc_login,name='login' ), 这种写法错误,r'^$/'要改成r'^$'

url(r'^$', views.dashboard,name='chat_dashboard' ),

url(r'^msg_send/$',views.send_msg,name='send_msg' ),

url(r'^new_msgs/$',views.get_new_msgs,name='get_new_msgs' ),

url(r'^file_upload/$',views.file_upload,name='file_upload' ),

]

然后在views.py中写一个file_upload视图

def file_upload(request):

print(request.POST)

return HttpResponse('dddddd')

先上传一个文件,查看下打印结果:

function UploadFiles(){

var formData = new FormData();

console.log($('#file_upload')[0].files[0]);

formData.append('file',$('#file_upload')[0].files[0]);

$.ajax({

url: "{% url 'file_uploads' %}",

type: 'POST',

data : formData,

processDate: false, //tell jQuery not to process the data

contentType: false, //tell jQuery not to set contentType

success: function(data){

console.log(data);

//alert(data);

}

});

}

结果我们测试有报错,chrome报错如下:

火狐浏览器报错如下:

按照火狐浏览器报出的错误查找到一片文章如下:

平时做表单都是跳转提交的,但是今天要做一个ajax图片异步上传,

网上搜索了下,方法都比较老了,居然还有用flash的,

普通的表单上传通过jquery的serialize()转换成querystring后就可以直接ajax post 上传,但是碰到文件上传就不奏效了,型号html5有个方法FormData()可以实现上传,

我写的代码如下:

function upThumbSubmit() {

if(!window.FormData) {

alert('your brower is too old');

return false;

}

var formData = new FormData($( "#upForm" )[0]);

$.ajax({

url:'?c=api&a=upload',

type:'post',

data:formData,

dataType:'json',

success:function(data){

alert(data);

return false;

}

});

}

但是报错了,错误如下

TypeError: 'append' called on an object that does not implement interface FormData.

既然浏览器明明显示支持formdata,为何这里显示append不是formdata接口呢?

答案只可能是jquery重载了formdata

在里面加上2个option,就好了,正确代码如下

function upThumbSubmit() {

if(!window.FormData) {

alert('your brower is too old');

return false;

}

var formData = new FormData($( "#upForm" )[0]);

$.ajax({

url:'?c=api&a=upload',

type:'post',

data:formData,

processData: false,

contentType: false,

dataType:'json',

success:function(data){

alert(data);

return false;

}

});

}

才发现自己写错了,如下:

这个小错误,我整了3小时。

还好解决了,更改后,上传文件测试,看看后台打印什么?

结果为空,那是不是ajax没把文件传过来。当然不是,是文件不能用request.POST获取,而是用request.FILES

更改视图函数如下:

def file_upload(request):

print(request.POST,request.FILES)

print("22222")

return HttpResponse('dddddd')

在此上传打印如下:

我们看文件句柄已经传给后台了。那么接下来就修改视图函数把文件存下来就行了。

def file_upload(request):

print(request.POST,request.FILES)

file_obj = request.FILES.get('file')

new_file_name = "uploads/%s"%file_obj.name

with open(new_file_name,"wb+") as new_file_obj:

for chunk in file_obj.chunks():

new_file_obj.write(chunk)

return HttpResponse('--upload success---')

后台异步接收文件,请参照《python2.0_day21_bbs系统评论自动加载+文章创建》一节中的解释。

然后我们前端上传,看看后端uploads目录下有没有该文件。如图

哈哈,文件已经上传成功了。

现在是实现了异步上传文件。但是我们是不是想看到文件上传的进度。如何实现呢?

接下来还有两个功能,一个是上传文件的进度条显示,

一个是把图片显示到聊天窗口,这里不想看了。2周后再补上。因为我已经等不及看主机管理章节了。因为那是我现在能用到的

废话不多说,咱开始。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值