web聊天室
开发一个web聊天室
功能需求:
1、用户可以与好友一对一聊天
2、群聊
所需知识
1、Django
2、bootstrap
3、CSS
4、ajax
涉及到的新的知识点
1、如果设计表结构的时候,一张表中有一个以上的字段关联另外一张相同的表(外键),那么直接关联会出错,合适的方法是使用related_name指定一个名字就可以解决,如下members和admins.
class QQgroup(models.Model):
name =models.CharField(max_length=,unique=True)
members=models.ManyToManyField(UserProfile,blank=True) #null =True无效
admins=models.ManyToManyField(UserProfile,related_name='group_admins') #在model中存在同时存在两个字段关联一张表,这样的会出错,需要使用related_name将名字修改一下来解决
max_member_nums=models.IntegerField(default=)
2、在views或者js代码中,如果需要调用不同的函数,指向函数的url可以通过name名直接调用函数,而无需写url的真实路径,多个name可以同时指向同一个url,如下new_msg,另外,url建议使用名词,养成良好的编码习惯。
urlpatterns = patterns('', url(r'dashboard/$', views.dashboard,name='web_chat'),
url(r'contacts/$', views.contacts,name='load_contact_list'), #url全部使用名词,符合规范
url(r'msg/$', views.new_msg,name='send_msg'), #url全部使用名词,符合规范
url(r'msg/$', views.new_msg,name='get_new_msgs'),
)
3、使用外键关联表自己的时候,不管是ForeignKey还是ManyToManyField,都需要related_name,如下friends字段:
class UserProfile(models.Model):
'''账户信息表'''
user=models.OneToOneField(User) #继承自带的User表,但是原生的user表中的字段较少,可以继承之后可以扩展字段;只能使用onetoone,否则就会使得多个用户同时关联一个账户onetoone是在代码层面进行限制的,其实就是讲两张表进行拼接了
name = models.CharField(max_length=)
groups=models.ManyToManyField('UserGroup')
friends=models.ManyToManyField('self',related_name='my_friends')
def __unicode__(self):
return self.name
contacts=request.user.userprofile.friends.select_related().values('id','name') #通过一个字段查看多对多,select_related查看所有的朋友,values表示需要查看的字段,为列表形式,元素为字典
4、如果开启了csrf验证功能,那么在Django form提交的时候,在模本中增加{% csrf_token %}即可,如果是ajax提交的数据,有两种方式让提交的数据添加csrf token;
a、在html模板中添加{% csrf_token %},将其埋在页面中,默认是hide的,通过页面元素审查,找到对应的input下的name为csrfmiddlewaretoken,将其value值通过函数在POST提交的时候,添加到提交的数据中,但是这种方式,每次POST数据都需要获取token并添加提交,不方便;
function GetCsrfToken(){
return $("input[name='csrfmiddlewaretoken']").val(); //获取csrftoken的值
//每次post提交数据都需要将csrf token的值获取出来进行post提交,有点low
} function SendMsg(msg_text){ //通过ajax 将数据进行提交
var contact_id = $(".chat-header span").attr("contact_id");
var contact_type = $(".chat-header span").attr("contact_type");
var msg_dic={
'contact_type':contact_type,
'to':contact_id,
'from':"{{ user.userprofile.id }}",
'from_name':"{{ user.userprofile.name }}",
'msg':msg_text
};
console.log("{{ user.userprofile.id }}");
console.log("{{ user.userprofile.name }}");
//$.post("{% url 'send_msg' %}",{'data':JSON.stringify(msg_dic),'csrfmiddlewaretoken':GetCsrfToken()},function(callback){ //csrfmiddlewaretoken提交的时候讲csrf的值一起提交
$.post("{% url 'send_msg' %}",{'data':JSON.stringify(msg_dic)},function(callback){ //使用插件,csrfmiddlewaretoken提交的时候讲csrf的值一起提交
console.log(callback); //函数的返回值为callback,采用回调函数
}); //end post JSON.stringify(msg_dic)将字典转换为json格式
}
b、使用插件提交
//csrf ref
//获取csrf token并添加到每一次post的数据中
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = ; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(, name.length + ) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + ));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken'); function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
// end csrf ref
5、正向或者反向获取数据库外键关联表的字段值
contacts=request.user.userprofile.friends.select_related().values('id','name') #通过一个字段查看多对多,select_related(外键关联的所有实体)查看所有的朋友,values表示需要查看的字段,为列表形式,元素为字典
print contacts
contact_dic['contact_list']=list(contacts) #显示为列表,其实还是django的对象,需要强制转换为列表
groups=request.user.userprofile.qqgroup_set.select_related().values('id','name','max_member_nums') #、获取群组,qqgroup_set这种方法适用于自己没有和别的表关联,但是别的表和自己关联了
#、如果不使用上述方法,就需要从QQgroup表的member中过滤出包含自己名字的组名,添加
#a=models.QQgroup.object.all(); for i in a:print i.members.select_related()
聊天室几种实现方式:
http请求是短链接、无状态
客户端cookie中保存的是session id,每次,对于同义词session请求,客户端会携带session id与服务器进行交互,这样对于无状态的http请求,服务端就会知道这次请求与上次请求的关系;
客户端连接上服务器之后,会阻塞,如果客户端有新消息发送过来的时候,就会唤醒,属于一种长轮询方式;
另外一种解决方式是WebSocket(长连接),通过浏览器(支持h5的浏览器)和服务器(支持长连接)端建立socket来快速实现;Django不支持长连接;
表结构设计:
class UserProfile(models.Model):
'''账户信息表'''
user=models.OneToOneField(User) #继承自带的User表,但是原生的user表中的字段较少,可以继承之后可以扩展字段;只能使用onetoone,否则就会使得多个用户同时关联一个账户onetoone是在代码层面进行限制的,其实就是讲两张表进行拼接了
name = models.CharField(max_length=)
groups=models.ManyToManyField('UserGroup')
friends=models.ManyToManyField('self',related_name='my_friends') #每一个用户都有自己的多个好友,好友也可以有多个好友;
def __unicode__(self):
return self.name
webchat\model.py
from django.db import models
from web.models import UserProfile
# Create your models here. class QQgroup(models.Model):
name =models.CharField(max_length=,unique=True)
members=models.ManyToManyField(UserProfile,blank=True) #null =True无效
admins=models.ManyToManyField(UserProfile,related_name='group_admins') #在model中存在同时存在两个字段关联一张表,这样的会出错,需要使用related_name将名字修改一下来解决
max_member_nums=models.IntegerField(default=)
表结构创建完成之后,利用admin进行创建数据
WEB聊天室页面布局
将聊天的url分发到自己的应用当中
from django.conf.urls import patterns, include, url
from django.contrib import admin
from web import views
from webchat import urls as chat_urls urlpatterns = patterns('',
# Examples:
# url(r'^$', 'js.views.home', name='home'),
# url(r'^blog/', include('blog.urls')), url(r'^admin/', include(admin.site.urls)),
url(r'^chat/', include(chat_urls)),
webchat\urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
import views urlpatterns = patterns('', url(r'dashboard/', views.dashboard,name='web_chat'),
)
webchat\views.py
from django.shortcuts import render
def dashboard(request):
return render(request,'web_chat/dashboard.html')
dashboard.html:整个包含在一个大的div中,分为左右两个小的div(加row属性),占3/12,右边占9/12,右边的div分为3部分,顶部chat-header,中部chat-content,和底部chat-msg-sendbox(分为左右两部分);
{% extends 'index.html' %} {% block page-container %}
<h1>撩妹专区.....</h1>
<div class="chat-container row">
<div class="contact-list col-md-3">
contact list
</div>
<div class="chat-box col-md-9">
chat box
<div class="chat-header"> talking with ...now</div>
<div class="chat-content">content</div>
<div class="chat-msg-sendbox row">
<div class="msg-box col-md-10">
<textarea></textarea>
</div>
<div class="msg-box-tn col-md-2">
<button type="button" class="btn btn-success">发送</button>
</div>
</div>
</div> </div>
{% endblock %}
{% block bottom-js %}
<script>
$(document).delegate("textarea","keydown", function (e) {
if(e.which==){
var msg_text=$("textarea").val();
if($.trim(msg_text).length>){
//SendMsg(msg_text);
console.log(msg_text);
//AddSendMsgIntoBox(msg_text);
//$("textarea").val(''); }
}
})
</script>
{% endblock %}
web聊天室的更多相关文章
- 使用Servlet和JSP实现一个简单的Web聊天室系统
1 问题描述 利用Java EE相关技术实现一个简单的Web聊天室系统,具体要求如下. (1)编写一个登录 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室 实战系列
ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言 http://www.cnblogs.com/panzi/p/5742089.html ASP.NET S ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十二) 代码重构使用反射工厂解耦(一)缓存切换
前言 上一篇中,我们用了反射工厂来解除BLL和UI层耦合的问题.当然那是最简单的解决方法,再复杂一点的程序可能思路相同,但是在编程细节中需要考虑的就更多了,比如今天我在重构过程中遇到的问题.也是接下来 ...
- 利用html 5 websocket做个山寨版web聊天室(手写C#服务器)
在之前的博客中提到过看到html5 的websocket后很感兴趣,终于可以摆脱长轮询(websocket之前的实现方式可以看看Developer Works上的一篇文章,有简单提到,同时也说了web ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言
前端时间听一个技术朋友说 LayIM 2.0 发布了,听到这个消息抓紧去官网看了一下.(http://layim.layui.com/)哎呀呀,还要购买授权[大家支持一下哦],果断买了企业版,喜欢钻研 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取)
大家好,本篇是接上一篇 ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言 ASP.NET SignalR WebIM系列第二篇.本篇会带领大家将 LayIM ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(二) 之 ChatServer搭建,连接服务器,以及注意事项。
上篇:ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取) 上一篇我们已经完成了初步界面的搭建工作,本篇将介绍IM的核心内容 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(三) 之 实现单聊,群聊,发送图片,文件。
上篇讲解了如何搭建聊天服务器,以及客户端js怎么和layui的语法配合.服务器已经连接上了,那么聊天还会远吗? 进入正题,正如上一篇提到的我们用 Client.Group(groupId)的方法向客户 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(四) 之 用户搜索(Elasticsearch),加好友流程(1)。
前面几篇基本已经实现了大部分即时通讯功能:聊天,群聊,发送文件,图片,消息.不过这些业务都是比较粗犷的.下面我们就把业务细化,之前用的是死数据,那我们就从加好友开始吧.加好友,首先你得知道你要加谁.L ...
随机推荐
- 常用Web Service汇总(天气预报、时刻表等)
现成的Web Service中有很多很好用的,比如天气预报,IP地址搜索,火车时刻表等等.本文汇总的一些常用Web Service,希望对大家有所帮助. AD: ================= ...
- UICollectionView的使用小记录和一些说明
// // MallTestViewController.h // fitmiss // // Created by bill on 16/6/28. // Copyright © 2016年 lea ...
- IOS开发--自定义segment控件,方便自定义样式
系统的segment控件太封闭,想换个颜色加个背景太难了,忍不住自己写一个,以备不时之需 这个控件给出了很多自定义属性的设置,用起来还是比较方便的,需要注意的 itemWidth如果不设置,则会按照控 ...
- 十大Intellij IDEA快捷键(转)
1 智能提示 Intellij首当其冲的当然就是Intelligence智能!基本的代码提示用Ctrl+Space,还有更智能地按类型信息提示Ctrl+Shift+Space,但因为Intellij总 ...
- Spring3.1新特性(转)
一.Spring2.5之前,我们都是通过实现Controller接口或其他实现来定义我们的处理器类. 二.Spring2.5引入注解式处理器支持,通过@Controller 和 @RequestMap ...
- Ubuntu14.04安装搜狗拼音输入法
删除ibus输入法 sudo apt-get purge ibus sudo apt-get autoremove 安装fcitx和拼音输入法 sudo apt-get install fcitx f ...
- 【linux编程】linux中HZ和Jiffies的关系
读cubic源码的时候遇到了HZ和jiffies,不懂这两者代表什么.网上描述的是这样的 全局变量jiffies用来记录自系统启动以来产生的节拍的总数.启动时,内核将该变量初始化为0,此后,每次时钟中 ...
- double四舍五入,商品金额大小写转换,设置货币的小数位数跟格式输出,进制转化
1:计算double值四舍五入的方法 对小数数值进行四舍五入,首先应该确认保留小数位, 如果数值的小数精度大于保留小数位,那么开始四舍五入计算.四舍五入的方法非常简单,在所有要丢失精度的小数位中加 ...
- (推荐)WPF动画教程
无意间发现博主的文章,记录推荐一下. http://www.cnblogs.com/alamiye010/archive/2009/06/17/1505346.html http://www.cnbl ...
- IIS7下ajax报未定义错误
项目之前在iis6环境下运行的很好,今天在WIN7下发布,结果居然报对象未定义错误,经过个把小时折腾,终于弄清楚原委. 在web.config中关于AjaxPro的设置,在IIS7.0(WIN7中使用 ...