开发一个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聊天室的更多相关文章

  1. 使用Servlet和JSP实现一个简单的Web聊天室系统

    1 问题描述                                                利用Java EE相关技术实现一个简单的Web聊天室系统,具体要求如下. (1)编写一个登录 ...

  2. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室 实战系列

    ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言  http://www.cnblogs.com/panzi/p/5742089.html ASP.NET S ...

  3. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十二) 代码重构使用反射工厂解耦(一)缓存切换

    前言 上一篇中,我们用了反射工厂来解除BLL和UI层耦合的问题.当然那是最简单的解决方法,再复杂一点的程序可能思路相同,但是在编程细节中需要考虑的就更多了,比如今天我在重构过程中遇到的问题.也是接下来 ...

  4. 利用html 5 websocket做个山寨版web聊天室(手写C#服务器)

    在之前的博客中提到过看到html5 的websocket后很感兴趣,终于可以摆脱长轮询(websocket之前的实现方式可以看看Developer Works上的一篇文章,有简单提到,同时也说了web ...

  5. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言

    前端时间听一个技术朋友说 LayIM 2.0 发布了,听到这个消息抓紧去官网看了一下.(http://layim.layui.com/)哎呀呀,还要购买授权[大家支持一下哦],果断买了企业版,喜欢钻研 ...

  6. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取)

    大家好,本篇是接上一篇 ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言  ASP.NET SignalR WebIM系列第二篇.本篇会带领大家将 LayIM ...

  7. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(二) 之 ChatServer搭建,连接服务器,以及注意事项。

    上篇:ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取) 上一篇我们已经完成了初步界面的搭建工作,本篇将介绍IM的核心内容 ...

  8. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(三) 之 实现单聊,群聊,发送图片,文件。

    上篇讲解了如何搭建聊天服务器,以及客户端js怎么和layui的语法配合.服务器已经连接上了,那么聊天还会远吗? 进入正题,正如上一篇提到的我们用 Client.Group(groupId)的方法向客户 ...

  9. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(四) 之 用户搜索(Elasticsearch),加好友流程(1)。

    前面几篇基本已经实现了大部分即时通讯功能:聊天,群聊,发送文件,图片,消息.不过这些业务都是比较粗犷的.下面我们就把业务细化,之前用的是死数据,那我们就从加好友开始吧.加好友,首先你得知道你要加谁.L ...

随机推荐

  1. ubuntu 更换系统语言,Change System Language

    1.打开设置,打开“Language Support”. 2.如果列表中没有你的语言,点击“Install/Remove Language”,下拉选择你的语言,点击“Apply Changes”. 3 ...

  2. NC营改增

    收票 select * from jzinv_receive  where vinvno='04888118' 1045select * from bd_corp where pk_corp='104 ...

  3. AES--高级数据加密标准

    AES--高级数据加密标准 对称密码体制的发展趋势将以分组密码为重点.分组密码算法通常由密钥扩展算法和加密(解密)算法两部分组成.密钥扩展算法将b字节用户主密钥扩展成r个子密钥.加密算法由一个密码学上 ...

  4. HTML DOM元素的Dragdrop

    在前端web页面中,为了提高用户体验,通常会希望将页面中的元素设计成可dragdop的,简化用户操作.这一设计特性在缺少鼠标的触摸屏设备上,显得更为重要. 在早期的应用中,我们通常需要借助第三方的ja ...

  5. 51nod 1643 小Q的家庭作业

    题意: f(n) = sigma(gcd(i,n))  1 <= i <= n g(n) = sigma(f(d))    d | n n = x1 * x2 * ... * xm 其中 ...

  6. 标签中id和name的作用和区别

    id:作为标签的唯一标识.name:作为可与服务器交互数据的HTML元素的服务器端的标示.

  7. [DFNews] Blackbag发布MacQuisition 2013 R2

    New in MacQuisition 2013 R2: Improved FileVault 2 Detection - Automatically detect the presence of a ...

  8. 支持ASP.NET WebService

    ASP.NET WebService默认返回的数据格式是XML,但也能返回JSON格式. 如何让MiniUI组件支持ASP.NET WebService? 只需要: 1) 引用miniui-webse ...

  9. Why is Visual Studio 2015 not able to find or open PDB files?

    first change parameters, Tools->Options->Debugging->Symbols->Microsoft Symbol Server, ye ...

  10. excel导出字符串

     "style", "vnd.ms-excel.numberformat: @;"