Django:之BBS项目

首先新建一个BBSProject项目,在建一个app,把app导入到项目中。

在项目BBSProject中的settings.py中,

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',#导入app01
    
]

url设置,在BBSProject的urls里导入app01中的views,

from django.conf.urls import url
from django.contrib import admin
from app01 import views#导入app01中的views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', views.index),#设置默认首页访问页面
]

在访问index的时候返回的结果是,在app01中的views中设置的index函数。

#_*_coding:utf-8_*_
from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
    return HttpResponse(u"欢迎访问吴老二博客")

测试简单页面

在做一个bbs之前首先要考虑的是数据库的框架,在一个bbs中需要的内容,还有就是数据库之间的的联用一定要清晰。

注:一个bbs首先要有用户,要有内容,不同的板块,还要有评论,点赞还有就是用户组。

#_*_coding:utf-8_*_
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
'''用户组表,用户组名称不能相同,长度为64,返回用户组名
'''
class UserGroup(models.Model):

    name = models.CharField(max_length=64,unique=True)

    def __unicode__(self):
        return self.name
'''用户信息表,包括用户名,用户组,
'''
class UserProfile(models.Model):

    user = models.OneToOneField(User)
    name = models.CharField(max_length=32)
    groups = models.ManyToManyField(UserGroup)
    def __unicode__(self):
        return self.name
'''
帖子板块,长度.板块不能重复.用户权限
'''
class Category(models.Model):

    name = models.CharField(max_length=64,unique=True)
    admin = models.ManyToManyField(UserProfile)
    def __unicode__(self):
        return self.name
'''帖子数据库表,标题,需要设置标题长度,标题不能重复.帖子隶属于板块,帖子插入的图片存储位置,内容以及优先级,帖子内容长度,帖子发布者需要联用用户列表,
如果用户列表在帖子列表下面需要加双引号.
    '''
class Article(models.Model):

    title = models.CharField(u"文章标题",max_length=255,unique=True)
    categroy = models.ForeignKey(Category,verbose_name=u"板块")
    head_img = models.ImageField(upload_to="uploads")
    summary = models.CharField(max_length=255)
    content = models.TextField(u"内容")
    author = models.ForeignKey(UserProfile)
    publish_date = models.DateTimeField(auto_now=True)
    hidden = models.BooleanField(default=True)
    priority = models.IntegerField(u"优先级",default=1000)

    def __unicode__(self):
        return "<%s, author:%s>" %(self.title,self.author)


'''
评论数据库表,评论的帖子需要联用帖子列表,评论者需要调用用户表,评论内容
'''
class Comment(models.Model):

    article = models.ForeignKey(Article)
    user = models.ForeignKey(UserProfile)
    parent_comment = models.ForeignKey('self',related_name='p_comment',blank=True,null=True)
    comment = models.TextField(max_length=1000)
    date = models.DateTimeField(auto_now=True)
    def __unicode__(self):
        return "<%s, user:%s>" %(self.comment,self.user)
'''点赞表点赞时间,点赞的帖子,和点赞者'''
class ThumbUp(models.Model):

    article = models.ForeignKey(Article)
    user = models.ForeignKey(UserProfile)
    date = models.DateTimeField(auto_now=True)
    def __unicode__(self):
        return "<user:%s>" %(self.user)
models

建好数据库需要同步一下:

python manage.py makemigrations  
python manage.py migrate

开始写页面返回views

#_*_coding:utf-8_*_
from django.shortcuts import render,HttpResponseRedirect
import models
from django.core.exceptions import ObjectDoesNotExist
from django.contrib.auth import authenticate,login,logout
from forms import ArticleForm,handle_uploaded_file
# Create your views here.
def index(request):
    '''首页'''
    articles = models.Article.objects.all()
    return render(request,'index.html',{'articles': articles})
def category(request,category_id):
    '''二级分类'''
    articles = models.Article.objects.filter(categroy_id=category_id)
    return render(request,'index.html',{'articles': articles})

def article_detail(request,article_id):
    '''帖子内容'''
    try:
        article_obj = models.Article.objects.get(id=article_id)
    except ObjectDoesNotExist as e:
        return render(request,'404.html',{'err_msg':u"文章不存在!"})
    return render(request,'article.html', {'article_obj':article_obj})
def acc_logout(request):
    '''退出登陆'''
    logout(request)
    return HttpResponseRedirect('/')
def acc_login(request):
    '''登陆'''
    print(request.POST)
    err_msg =''
    if request.method == "POST":
        print('user authention...')
        username = request.POST.get('username')
        password = request.POST.get('password')
        user = authenticate(username=username,password=password)
        if user is not None:
            login(request,user)
            return HttpResponseRedirect('/')
        else:
            err_msg = "Wrong username or password!"
    return render(request,'login.html',{'err_msg':err_msg})


def new_article(request):
    '''最新帖子'''
    if request.method == 'POST':
        print(request.POST)
        form = ArticleForm(request.POST,request.FILES)
        if form.is_valid():
            print("--form data:",form.cleaned_data)
            form_data = form.cleaned_data
            form_data['author_id'] = request.user.userprofile.id

            new_img_path = handle_uploaded_file(request,request.FILES['head_img'])
            form_data['head_img'] = new_img_path
            new_article_obj = models.Article(**form_data)
            new_article_obj.save()
            return  render(request,'new_article.html',{'new_article_obj':new_article_obj})
        else:
            print('err:',form.errors)
    category_list = models.Category.objects.all()
    return render(request,'new_article.html', {'categroy_list':category_list})
views

路径urls

#_*_coding:utf-8_*_

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$',views.index, name="index" ),
    url(r'^category/(d+)/$',views.category,name="category" ),
    url(r'^article/(d+)/$',views.article_detail,name="article_detail"),
    url(r'^article/new/$',views.new_article,name="new_article"),
    url(r'account/logout/',views.acc_logout,name='logout'),
    url(r'account/login/',views.acc_login,name='login'),

]

可以登陆管理员后台建立板块和用户,发布帖子,帖子存放路径需要新建一个forms在app01里。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django import forms
import os
class ArticleForm(forms.Form):
    '''帖子路径包括标题,内容作者,图片'''
    title = forms.CharField(max_length=255,min_length=5)
    summary  = forms.CharField(max_length=255,min_length=5)
    categroy_id = forms.IntegerField()
    head_img = forms.ImageField()
    content = forms.CharField(min_length=10)

def handle_uploaded_file(request,f):
    '''帖子图片存储路径'''
    base_img_upload_path = 'statics/imgs'
    user_path = "%s/%s" %(base_img_upload_path,request.user.userprofile.id)
    if not os.path.exists(user_path):
        os.mkdir(user_path)
    with open("%s/%s" %(user_path,f.name), 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)
    return  "/static/imgs/%s/%s" %(request.user.userprofile.id,f.name)

关于帖子的评论需要考虑级别,在app01里新建一个tree_search_test评论函数。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
'''评论'''
data = [
    (None,'A'),
    ('A','A1'),
    ('A','A1-1'),
    ('A1','A2'),
    ('A1-1','A2-3'),
    ('A2-3','A3-4'),
    ('A1','A2-2'),
    ('A2','A3'),
    ('A2-2','A3-3'),
    ('A3','A4'),
    (None,'B'),
    ('B','B1'),
    ('B1','B2'),
    ('B1','B2-2'),
    ('B2','B3'),
    (None,'C'),
    ('C','C1'),

]
def tree_search(d_dic,parent,son):
    for k,v_dic in d_dic.items():
        if k == parent: #find your parent
            d_dic[k][son] = {}
            print("find parent of :", son)
            return
        else: # might in the deeper layer
            print("going to furhter layer...")
            tree_search(d_dic[k],parent,son)


data_dic = {}

for item in data:
    parent,son = item
    if parent is None:# has no parent
        data_dic[son] ={}
    else: #  looking for its parent
        tree_search(data_dic,parent,son)

for k,v in data_dic.items():
    print(k,v )

'''
data_dic = {
    'A': {
        'A1': {
            'A2':{
                'A3':{
                    'A4':{}
                }
            },
            'A2-2':{
                'A3-3':{}
            }
        }
    },
    'B':{
        'B1':{
            'B2':{
                'B3':{}
            },
            'B2-2':{}
        }
    },
    'C':{
        'C1':{}
    }

}'''
tree_search_test

一下是前台页面的处理,首先要设置语言和路径,在settings里设置。

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/

STATIC_URL = '/static/'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
    "%s/%s" %(BASE_DIR, "statics"),
    # "%s/%s" %(BASE_DIR, ""), #static/uploads/uploads/
)

html文件可以在下面下载。

index的导航部分

<div id="navbar" class="navbar-collapse collapse">
          <ul class="nav navbar-nav">
            <li ><a href="{% url 'index' %}">综合区</a></li>
            <li><a href="{% url 'category' 1 %}">欧美专区</a></li>
            <li><a href="{% url 'category' 2 %}">日韩专区</a></li>
            <li><a href="{% url 'category' 3 %}">河北专区</a></li>

          </ul>
          <ul class="nav navbar-nav navbar-right">

               {% if request.user.is_authenticated %}
                <li class="dropdown">
                  <a href="http://v3.bootcss.com/examples/navbar-fixed-top/#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ request.user.userprofile.name }} <span class="caret"></span></a>
                  <ul class="dropdown-menu">
                    <li><a href="{% url 'new_article' %}">发贴</a></li>
                    <li><a href="http://v3.bootcss.com/examples/navbar-fixed-top/#">Another action</a></li>
                    <li><a href="http://v3.bootcss.com/examples/navbar-fixed-top/#">Something else here</a></li>
                    <li role="separator" class="divider"></li>
                    <li class="dropdown-header">Nav header</li>
                    <li><a href="http://v3.bootcss.com/examples/navbar-fixed-top/#">Separated link</a></li>
                    <li><a href="{% url 'logout' %}">注销</a></li>
                  </ul>
                </li>
               {% else %}
                 <li><a href="{% url 'login'%}">注册登录</a></li>
               {% endif %}
          </ul>
        </div>

导航下分帖子展示和其他板块

<div class="container">
     {% block page-container %}
        <div class="row">
            <div class="col-md-8 left-content-panel">
                <div class="content-box">
                    {% for article in articles reversed %}
                        <div class="article-box row">
                            <div class="article-head-img col-md-3">
                                <img src="{{ article.head_img }}">
                            </div>
                            <div class="article-summary col-md-8">
                                <h4><a href="{% url 'article_detail' article.id %}">{{ article.title }}</a></h4>
                                <div class="article-attr">
                                    <ul  class="list-inline">
                                        <li>{{ article.author.name }}</li>
                                        <li>{{ article.publish_date }}</li>
                                        <li>thumbup:{{ article.thumbup_set.select_related.count }}</li>
                                        <li>comments:{{ article.comment_set.select_related.count }}</li>
                                    </ul>
                                </div>
                                <p>{{ article.summary }}</p>
                            </div>
                        </div>
                         <hr >
                    {% endfor %}

                </div>
            </div>
            <div class="col-md-4 right-sidebar">
                bar
            </div>
        </div>
     {% endblock %}
    </div>

js的调用

    <script src="/static/bootstrap/js/jquery-2.1.4.js"></script>
    <script src="/static/bootstrap/js/bootstrap.min.js"></script>
    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
    <script src="/static/bootstrap/js/ie10-viewport-bug-workaround.js"></script>
    <script type="text/javascript">
        $(document).ready(function(){
            var menus = $("#navbar a[href='{{ request.path }}']")[0];
            $(menus).parent().addClass("active");
            $(menus).parent().siblings().removeClass("active");
            //console.log(menus);
        });

    </script>

    {% block bottom-js %}
   {% endblock %}

登陆页面

{% extends 'index.html' %}


{% block page-container %}

<div class="col-md-4">
    <form class="form-signin" action="{% url 'login' %}" method="post">{% csrf_token %}
        <h2 class="form-signin-heading">Please sign in</h2>
        <label for="inputEmail" class="sr-only">用户名</label>
        <input type="text" id="" name="username" class="form-control" placeholder="username" required="" autofocus="">
        <label for="inputPassword" class="sr-only">Password</label>
        <input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required="">
        <div class="checkbox">
          <label>
            <input type="checkbox" value="remember-me"> Remember me
          </label>
        </div>
        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
        <p style="color:red;">{{ err_msg }}</p>
    </form>
</div>


{% endblock %}

最新帖子

{% extends 'index.html' %}
{% block head-js %}
   <script src="/static/plugins/ckeditor/ckeditor.js"></script>
{% endblock %}

{% block page-container %}
   <div class="new-article">
    {% if new_article_obj %}
        <h3>文章<{{ new_article_obj.title }}>已发布,<a href="{% url 'article_detail' new_article_obj.id %}"> 点我查看</a></h3>
    {% else %}
       <form  enctype="multipart/form-data" method="post" action="{% url 'new_article' %}">{% csrf_token %}
        <input name="title" type="text" class="form-control" placeholder="文章标题">
        <select name="categroy_id" class="form-control">
          {% for category in categroy_list %}
            <option value="{{ category.id }}">{{ category.name }}</option>
          {% endfor %}
        </select>
        <input name="summary" type="text" class="form-control" placeholder="一句话文章中心思想...">
        <input type="file" name="head_img">必选文章标题图片
        <textarea id="ck-editor" name="content" class="form-control" rows="3"></textarea>

        <br/>
       <button type="submit" class="btn btn-success pull-right">发贴</button>

    </form>
    {% endif %}
   </div>
{% endblock %}

{% block bottom-js %}
    <script>
         CKEDITOR.replace( 'ck-editor' );
        CKEDITOR.editorConfig = function( config ) {
            //config.language = 'es';
            config.uiColor = '#F7B42C';
            config.height = 500;
            config.toolbarCanCollapse = true;
        };
    </script>
{% endblock %}

所有帖子

{% extends 'index.html' %}
{% load custom_tags %}

{% block page-container %}
   <div class="article-detail">
        <h4>{{ article_obj.title }}</h4>

        <p>{{ article_obj.content|safe }}</p>

        <hr/>
        {%  build_comment_tree article_obj.comment_set.select_related %}
   </div>
{% endblock %}

报错404

{% extends 'index.html' %}


{% block page-container %}
    <h1 style="font-size: 200px">404</h1>
    <h3>{{ err_msg }}</h3>
{% endblock %}

以上是一个简单的bbs的搭建和制作,参考文件  

webqq聊天室

webqq聊天室就给予上面的bbs制作吧,首先是数据库

在app01的数据库的用户信息表中新建朋友表。

class UserProfile(models.Model):
    '''
    用户信息表,包括用户名,用户组,
    '''
    user = models.OneToOneField(User)
    name = models.CharField(max_length=32)
    groups = models.ManyToManyField('UserGroup')
    friends = models.ManyToManyField('self', related_name='my_friends')#新加的朋友表
    def __unicode__(self):
        return self.name

新建一个webqq项目,数据库中新建聊天组。

from __future__ import unicode_literals

from django.db import models
from app01.models import UserProfile
# Create your models here.
class QQGroup(models.Model):
    name = models.CharField(max_length=64,unique=True)
    description = models.CharField(max_length=255,default="nothing...")
    members = models.ManyToManyField(UserProfile,blank=True)
    admins = models.ManyToManyField(UserProfile,related_name='group_admins')
    max_member_nums = models.IntegerField(default=200)
    def __unicode__(self):
        return self.name

聊天组的views

#_*_coding:utf-8_*_
from django.shortcuts import render,HttpResponse
from webqq import models
import json,Queue,time
from django.contrib.auth.decorators import login_required#登录判断

# Create your views here.
GLOBAL_MQ = {}


@login_required

def dashboard(request):
    return render(request,'webqq/dashboard.html')
'''聊天页面函数返回聊天页面
'''
@login_required
def contacts(request):
    contact_dic = {
        #'contact_list': [],
        #'group_list': [],
    }
    contacts = request.user.userprofile.friends.select_related().values('id','name')
    contact_dic['contact_list']= list(contacts)
    groups = request.user.userprofile.qqgroup_set.select_related().values("id",'name','max_member_nums')
    contact_dic['group_list'] = list(groups)
    print(contact_dic)
    return HttpResponse(json.dumps(contact_dic))
'''好有聊天,以及群组聊天
'''
@login_required
def new_msg(request):
    if request.method == 'POST':
        print('-->',request.POST.get('data'))

        data = json.loads(request.POST.get('data'))
        send_to = data['to']
        msg_from = data["from"]
        contact_type = data['contact_type']
        data['timestamp'] = time.time()
        if contact_type == 'group_contact':
            group_obj = models.QQGroup.objects.get(id=send_to)
            for member in group_obj.members.select_related():
                if  str(member.id) not in  GLOBAL_MQ:
                    GLOBAL_MQ[str(member.id)] = Queue.Queue()
                if str(member.id) != msg_from:
                    GLOBAL_MQ[str(member.id)].put(data)

        else:
            if  send_to not in  GLOBAL_MQ:
                GLOBAL_MQ[send_to] = Queue.Queue()
            GLOBAL_MQ[send_to].put(data)
        return HttpResponse(GLOBAL_MQ[send_to].qsize())
    else:#recv msgs
        request_user = str(request.user.userprofile.id)
        msg_lists = []
        print(GLOBAL_MQ,request_user)
        if request_user in GLOBAL_MQ:
            print("hehe")
            stored_msg_nums = GLOBAL_MQ[request_user].qsize()
            if stored_msg_nums ==0: #no new msgs
                try:
                    print("33[41;1mNo new msg , wait for 60 secs...33[0m")
                    msg_lists.append(GLOBAL_MQ[request_user].get(timeout=15))
                except Exception as e:
                    print("err:",e)
                    print("33[41;1mtime out or new msgs....33[0m ")

            for i in range(stored_msg_nums):
                msg_lists.append(GLOBAL_MQ[request_user].get())
        else:
            #create a new queue for this user
            GLOBAL_MQ[str(request.user.userprofile.id)] = Queue.Queue()
        return  HttpResponse(json.dumps(msg_lists))
'''聊天消息发送,首先是判断是群组聊天还是个人聊天,群组聊天直接进去群组,个人聊天直接返回个人,根据不同的聊天对象发送消息,并且返回
'''
webqq.Views

BBSProject项目的url把webqq的url导入进去进去。

from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
from webqq import urls as char_urls
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^chat/', include(char_urls)),#webqq的url
    url(r'^$',views.index, name="index" ),
    url(r'^category/(d+)/$',views.category,name="category" ),
    url(r'^article/(d+)/$',views.article_detail,name="article_detail"),
    url(r'^article/new/$',views.new_article,name="new_article"),
    url(r'account/logout/',views.acc_logout,name='logout'),
    url(r'account/login/',views.acc_login,name='login'),

]

webqq下新建一个url

from django.conf.urls import include, url
import views

urlpatterns = [

    url(r'dashboard/$',views.dashboard,name='webqq'),
    url(r'contacts/$',views.contacts,name='load_contact_list'),
    url(r'msg/$',views.new_msg,name='send_msg'),
    url(r'msg/$',views.new_msg,name='get_new_msgs'),
]

webqq下的tests信息

from django.test import TestCase

# Create your tests here.

def callMyself(n):
    print("level:",n )
    callMyself(n+1)
    print('111')
    return  0
callMyself(1)

webqq下的admin

from django.contrib import admin
from webqq import models
# Register your models here.
admin.site.register(models.QQGroup)

webqq下的apps 

from __future__ import unicode_literals

from django.apps import AppConfig


class WebqqConfig(AppConfig):
    name = 'webqq'

后台信息建好开始更新数据库  

python manage.py makemigrations  
python manage.py migrate

把前台的web数据编辑

{% extends 'index.html' %}


{% block page-container %}
    {% csrf_token %}
<h1>好基友聊天室</h1>
<div>

  <!-- Nav tabs -->
  <ul class="nav nav-tabs" role="tablist">
    <li role="presentation" chat-type="contact_list" contact-type="single_contact" class="active"><a href="#contacts"role="tab" data-toggle="tab">联系人</a></li>
    <li role="presentation" chat-type="group_list" contact-type="group_contact"><a onclick="LoadContacts();" href="#contacts" role="tab" data-toggle="tab">群组</a></li>
    <li role="presentation"><a href="#notifications"  role="tab" data-toggle="tab">通知</a></li>
    <li role="presentation"><a href="#settings"  role="tab" data-toggle="tab">配置</a></li>
  </ul>

  <!-- Tab panes -->
  <div class="tab-content">
    <div role="tabpanel" class="tab-pane active" id="contacts" >

        <div class="chat-container row">
    <div class="contact-list col-md-3">
        <div class="list-group">
        </div>

    </div>
    <div class="chat-box col-md-9">
        <div class="chat-header">

        </div>
        <div class="chat-content"> content</div>
        <div class="chat-msg-sendbox">
            <div class="msg-box col-md-10">
                <textarea></textarea>
            </div>
            <div class="msg-box-btn col-md-2">
               <button type="button" class="btn btn-success">发送</button>
            </div>
        </div>
    </div>
</div>


    </div>
    <div role="tabpanel" class="tab-pane" id="groups">profile...</div>
    <div role="tabpanel" class="tab-pane" id="notifications">...</div>
    <div role="tabpanel" class="tab-pane" id="settings">...</div>
  </div>

</div>




{% endblock %}

{% block bottom-js %}
<script>
//csrf ref
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                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


$(document).ready(function(){
        //load all contacts
        GLOBAL_SESSION_CACHE = {
            'single_contact':{},
            'group_contact':{}
        }
        LoadContacts();
        //var RefreshNewMsgs =  setInterval(function(){
        GetNewMsgs();
        //},31000);

            //send msg
        $("body").delegate("textarea", "keydown",function(e){
            if(e.which == 13) {//Enter key down
                //send msg button clicked
                var msg_text = $("textarea").val();
                if ($.trim(msg_text).length > 0){
                    console.log(msg_text);
                    SendMsg(msg_text);
                }
                //no wait the send_msg's call confirm msg
                AddSentMsgIntoChatBox(msg_text);
                $("textarea").val('');
            }
        });//end body
});//end doc ready
function AddRecvMsgToChatBox(msg_item){
    var msg_ele = "<div class='msg-item-recv'>" + "<p>" + msg_item.from_name + "   " + msg_item['timestamp'] + "</p>" +
                    "<p>" +  msg_item.msg + "</p>" +
                    "</div>";

    $(".chat-content").append(msg_ele);

    $('.chat-content').animate({
        scrollTop: $('.chat-content')[0].scrollHeight}, 500
    );//e
}
function GenerateNewMsgItem(msg_item){
    var msg_ele = "<div class='msg-item-recv'>" + "<p>" + msg_item.from_name + "   " + msg_item['timestamp'] + "</p>" +
                    "<p>" +  msg_item.msg + "</p>" +
                    "</div>";
    return msg_ele;
}

function AddSentMsgIntoChatBox(msg_text){
    var d = new Date();
    var send_time = d.getHours() + ":"+ d.getMinutes() + ":"+ d.getSeconds();
    var msg_ele = "<div class='msg-item-sent'>" + "<p>" + "{{ request.user.userprofile.name }}   " +
                    send_time + "</p>" +
                    "<p>" +  msg_text + "</p>" +
                    "</div>";
    $(".chat-content").append(msg_ele);

    $('.chat-content').animate({
        scrollTop: $('.chat-content')[0].scrollHeight}, 500
    );//e

}

function LoadContacts(){
    $.get("{% url 'load_contact_list' %}", function(callback){
        console.log(callback);
        var data = JSON.parse(callback);
        var current_tab = $(".nav-tabs li").filter(".active")[0];
        var chat_type = $(current_tab).attr("chat-type");
        var contact_type = $(current_tab).attr("contact-type");
        $(".contact-list .list-group").empty();
        $.each(data[chat_type], function(index, ele){
            var ele =  "<a href='#' onclick='OpenDialogBox(this);' class='list-group-item' contact_id='"+ ele.id +"' contact_type='"+contact_type +"' >" + ele.name +  "<span class='badge'>0</span></a>";
            $(".contact-list .list-group").append(ele);
        });//end each

    });//end get
}
function GetCsrfToken(){
    return $("input[name='csrfmiddlewaretoken']").val();
}
function OpenDialogBox(ele){
    var contact_id = $(ele).attr("contact_id");
    var contact_type = $(ele).attr("contact_type");
    var contact_name = $(ele).text();
    //dump current session contents
    DumpSession();

    var new_header = "<h4><span contact_id='" + contact_id + "'" + "contact_type='"+ contact_type+"'>Talking with " + contact_name +
                    "</span></h4>";
    $(".chat-header").html(new_header);
    $(".chat-content").html(LoadSession(contact_id,contact_type));

    //clear the unread msg num flags
    var unread_msg_num_ele = $(ele).find("span")[0];
    $(unread_msg_num_ele).text(0);

    $(unread_msg_num_ele).css("display","none");

}

function DumpSession(){
    var current_contact_id = $(".chat-header span").attr("contact_id");
    var current_contact_type= $(".chat-header span").attr("contact_type");
    //console.log($(".chat-content").html());
    console.log("contact id:::" +current_contact_id );
    if (current_contact_id){
        GLOBAL_SESSION_CACHE[current_contact_type][current_contact_id] =$(".chat-content").html();
    }
}
function DumpSession2(contact_id,contact_type,content){
    if (contact_id){
        GLOBAL_SESSION_CACHE[contact_type][contact_id] =content;
    }
}
function LoadSession(contact_id,contact_type){
    if (GLOBAL_SESSION_CACHE[contact_type].hasOwnProperty(contact_id) ){
        var session_html = GLOBAL_SESSION_CACHE[contact_type][contact_id];
    }else{
        var session_html = '';
    }
    return session_html;
    //$(".chat-content").html(session_html);
}

function SendMsg(msg_text){
    var contact_id = $(".chat-header span").attr("contact_id");
    console.log("contact_id" + contact_id);
    var contact_type = $(".chat-header span").attr("contact_type");
    var msg_dic = {
        'contact_type':contact_type,
        'to':contact_id,
        'from': "{{ request.user.userprofile.id }}",
        'from_name':"{{ request.user.userprofile.name }}",
        'msg':msg_text
    }
    //$.post("{% url 'send_msg' %}",{'data':JSON.stringify(msg_dic),'csrfmiddlewaretoken':GetCsrfToken()}, function(callback){
    $.post("{% url 'send_msg' %}",{'data':JSON.stringify(msg_dic)}, function(callback){
        console.log(callback);
    });//end post

}

function GetNewMsgs(){
    $.get("{% url 'get_new_msgs' %}",function(callback){
        console.log("new msgs:" + callback);
        var msg_list = JSON.parse(callback);
        var current_open_session_id = $(".chat-header span").attr("contact_id");
        var current_open_session_type = $(".chat-header span").attr("contact_type");
        $.each(msg_list, function(index,msg_item){
            if (msg_item.contact_type  == 'single_contact'){
                if (msg_item.contact_type == current_open_session_type){
                    if(msg_item.from == current_open_session_id){
                        AddRecvMsgToChatBox(msg_item);
                    }else{ // 代表这个session当前未被打开
                        var old_session_content = LoadSession(msg_item.from,msg_item.contact_type);
                        var new_msg_ele = GenerateNewMsgItem(msg_item);
                        var new_session_content  =old_session_content+ new_msg_ele;
                        DumpSession2(msg_item.from ,msg_item.contact_type,new_session_content)
                        UpdateUnreadMsgNums(msg_item.from ,msg_item.contact_type);
                    };//end if(msg_item.from == current_open_session_id)
                };//end if msg_item.contact_type == current_open_session_type
            }else{//for single contact
                if (msg_item.contact_type == current_open_session_type){

                    if (msg_item.to == current_open_session_id){
                        //current group dialog is opened...
                        AddRecvMsgToChatBox(msg_item);
                    }else{
                        var old_session_content = LoadSession(msg_item.to,msg_item.contact_type);
                        var new_msg_ele = GenerateNewMsgItem(msg_item);
                        var new_session_content  =old_session_content+ new_msg_ele;
                        DumpSession2(msg_item.to ,msg_item.contact_type,new_session_content);
                        UpdateUnreadMsgNums(msg_item.to ,msg_item.contact_type);

                    }
                }

            };// for group contact

        });//end each

        //start a new request again
        console.log("----run again....");
        GetNewMsgs();

    });//end get
}

function UpdateUnreadMsgNums(contact_id ,contact_type){
    var msg_num_ele = $(".contact-list a[contact_id='" + contact_id +"']").find("span")[0];
    $(msg_num_ele).text(   parseInt($(msg_num_ele).text()) + 1);
     $(msg_num_ele).show();
}

</script>
{% endblock %}

webqq聊天室制作完毕,有些功能还不太完善,但是给予聊天已经没有问题,  

 

原文地址:https://www.cnblogs.com/wulaoer/p/5343105.html