Created on 2017年5月15日 @author: louts
第1课 作业讲解及装饰器使用 28minutes
def check(func):
def rec(request,*args,**kargs):
return func(request,*args,**kargs)
return rec
@check
def index(request,):
print request
第2课 自定义装饰器扩展使用 18minutes
第3课
第4课 BBS功能分析及介绍 37minutes
分析网站的架构
自己写数据库Models
参考网站的前端来写一个页面
这节完成了页面头部的代码
第5课 BBS功能之点赞 40minutes
按HTML分几个部分
页头,内容,页尾
内容中按标题,内容,通过迭代数据库内容显示出来
参考页面写CSS和jQuery
可以在函数中定义好几个参数
item是数据的一条记录
<a href='' onclick='Favor(this,{{item.id}})'>点赞{{item.favor_count}}</a>
<script type='text/javascript'>
//jquery还是有错误,无法正常使用20170517
function Favor(doc,id){
$.ajax({
//注意Ajax里不能用冒号,要用逗号
url:'/addfavor/',
data:{id:id},
type:'POST',
sussess:function(arg){
console.log(arg);
var temp = '赞' + arg;
$(doc).text(temp);
}
})
2017/05/22
第6课 BBS功能之评论一 53minutes
思路:
点击 评论,触发Reply,Reyly去找父标签的下一个兄弟标签的第一个标签,对这个标签操作---目前这里实际操作失败
在这个标签下,定义输入框,和历史记录(记录用Ajax到数据库里取),对这个标签初始CSS为display:None
可以在这个标签里设定两个CSS,用于区别后台数据和当前输入框,找到历史的CSS,对这个标签做添加
前端:
-----------------------------------------------------------------------------------
<div class='part3'>
<a href='' onclick='Favor(this,{{item.id}})'>点赞{{item.favor_count}}</a>
<a href='' id='id1' onclick='Reply()'>评论{{item.reply_count}}</a>
<span>{{item.create_date|date:'Y-m-d H:i:s'}}</span>
</div>
<!-- 下面自定义一个属性has-input用于JAVA里的判断是否有穿入框了 -->
<div has-input=0 class='part4 hide'>
<!--这底下两个CSS用于下面Java的处理 -->
<div class='replys'></div>
<div class='input'>
<lable>请输入内容:</lable>
<textarea></textarea>
<input type='button' value='提交'>
</div>
</div>
function Reply(doc,id){
$.ajax(){
url:'/getreply/',
type:'POST',
data:{nid,id},
sussess:function(callback){
//callback是后台返回的数据
console.log(callback;)
var obj = jQuery.parseJSON(callback);
$.each(obj,function(k,v){
//当前标签和父亲标签的下一个标签的第一个标签
//$(doc).parent().next().first().text('0000')
var temp = '<p>' + v.fields.content + '</p>';
//这里找到.reply的CSS,先清除当前的内容,不然会出现重复
$(doc).parent().next().find('.replys').empty();
//这里找到.reply的CSS,再将返回的数据插进去
$(doc).parent().next().find('.replys').append(temp);
});
//这里点击时会去掉当前的hide的CSS
$(doc).parent().next().toggleClass('hide');
}
}
//console.log($('#content').attr('has-input'));
//$('#rid').removeClass('part4');
//toggleClass反复的加减CSS
//$('#content').toggleClass('hide');
var html = $('#id1').parent().next().first()
console.log(html)
//removeClass('hide');
}
后端:
-----------------------------------------------------------------------------------
def getreply(request):
id = request.POST.get('nic')
#这里可直接用外键__字段获取另一张表的内容 user__username new__id
reply_list = Reply.objcects.filter(new__id=id).values('id','content','user__username','create_date')
#json 无法序列化一个时间,可用serializers来操作
#serialize(format, queryset, **options)
reply_list = serializers.serialize('json', reply_list)
return HttpResponse(reply_list)
2017/05/24
第7课 BBS功能之评论二 55minutes
#用于Jason序列化时间格式
class CJsonEncoder(json.JSONEncoder):
def default(self,obj):
if isinstance(obj,datetime.datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(obj,date):
return obj.strftime('%Y-%m-%d')
else:
return json,JSONEncoder.default(self,obj)
def getreply(request):
id = request.POST.get('nic')
#这里可直接用外键__字段获取另一张表的内容 user__username new__id
reply_list = Reply.objcects.filter(new__id=id).values('id','content','user__username','create_date')
#json 无法序列化一个时间,可用serializers来操作
#serialize(format, queryset, **options)
'''
reply_list = serializers.serialize('json', reply_list)
return HttpResponse(reply_list)
'''
#用自己定义的类来处理时间格式
reply_list = list(reply_list)
json.dumps(reply_list,cls=CJsonEncoder)
return HttpResponse(reply_list)
提交评论,实时在页面上显示提交的内容(需提交到数据库中),同时自动更新评论的数量(也要更新数据库,并将数量返回给前台)
前端:
-----------------------------------------------------------------------------------
<div class='part3'>
<a href='' onclick='Favor(this,{{item.id}})'>点赞{{item.favor_count}}</a>
<a href='' class='reply' onclick='Reply(this,{{item.id}})'>评论{{item.reply_count}}</a>
<span>{{item.create_date|date:'Y-m-d H:i:s'}}</span>
</div>
<!-- 下面自定义一个属性has-input用于JAVA里的判断是否有穿入框了 -->
<div has-input=0 class='part4 hide'>
<!--这底下两个CSS用于下面Java的处理 -->
<div class='replys'></div>
<div class='input'>
<lable>请输入内容:</lable>
<textarea></textarea>
<!-- 这里添加item.id,是提交的时候要关联到这个新闻,不能放到其他的新闻里去
这里的this,一样通过此标签的上一个标签,就是提交的内容 -->
<input type='button' value='提交' onclick='Submit(this,{{item.id}})'>
</div>
</div>
{% endfor %}
</div>
<!-- 遮罩层开始 -->
<div id='shade' class='shade hide'></div>
<!-- 遮罩层结束 -->
<!-- 加载层开始 -->
<div id='loading' class='loading hide'></div>
<!-- 加载层结束 -->
function Submit(doc,id){
//上一个标签
var value = $(doc).prev().val();
//提交后清除输入框
$(doc).prev().val('');
$('#shade,loading').removeClass('hide');
$.ajax(){
url:'/submitreply/',
type:'POST',
data:{nid:id,data:value},
sussess:function(callback){
//callback是后台返回的数据
console.log(callback;)
var callback = jQuery.parseJSON(callback);
if (callback.status==1){
//把数据Append到回复列表中
temp = '<p>' + callback.data.username + ':' + callback.data.content + '---' + callback.data.create_date + '</p>';
$(doc).parent().prev().append(temp)
//底下两行代码可以让评论数实时的更新,添加一条时自动计数
//先提交到后台,正常保存后自动加1,同时将新的内容和数值提交到前台
count = '评论' + callback.data.reply_count
$(doc).parent().parent().prev().find('.reply').text(count)
}else{
alert('失败')}
}
$('#shade,loading').addClass('hide');
}
}
后端:
-----------------------------------------------------------------------------------
def submitreply(request):
ret = {'status':0,'data':'','message':''}
try:
id = request.POST.get('nid')
data = request.POST.get('data')
#获取新闻的对象
newsObj = News.objects.get(id=id)
obj = Reply.objects.create(content=data,
user=Admin.objects.get(id=request.session['current_user_id']),
new=newsObj)
#评论保存后同时要更新闻的评论条目,自动加1
temp = newsObj.reply_count + 1
newsObj.reply_count = temp
newsObj.save()
#将数量放到前端的字典中
ret['data']= {'reply_count':temp,'content':obj.content,
'user__name':obj.user.username,
'create_date':obj.create_date.strftime('%Y-%m-%d %H:%M:%S')}
ret['status'] = 1
except Exception,e:
ret['message'] = e.message
return HttpResponse(json.dumps(ret))
2017/05/31
第7课 BBS功能之Web聊天室 65minutes
思路:
-----------------------------------------------------------------------------------
文本框里输入信息,通过提交=====>触发一个函数=====>通过jQuery得到内容=====>发送到后台,
通过Ajax方式=====>后台根据获取的内容,加上时间和用户存到数据库中,并将相关内容再返回给
前台(文本的内容可以不返回)=====>前台接收到后台的数据,通过循环的方式,返回到显示框中
=====>可通过jQuery的层级查找的方式,找到Html标签,将内容Append到标签里
其中:
后台取数据,第一次时取最后10条,先倒序,得到最后的ID=====>第二次取的时间,这是另一个Ajax,
以这个ID为准,取大于此ID的数据,这样就可能取到最新的内容
另外聊天窗口每2秒更新一次,将最新的数据取出来,可以先定义一个变量为Ture,执行后变为False
前台:
-----------------------------------------------------------------------------------
//这是第7课的内容
function Reply(doc,id){
$.ajax(){
url:'/getreply/',
type:'POST',
data:{nid:id},
sussess:function(callback){
//callback是后台返回的数据
console.log(callback;)
var obj = jQuery.parseJSON(callback);
//放在这里,不会每次都清空掉,这样可以显示所有记录
$(doc).parent().next().find('.replys').empty();
$.each(obj,function(k,v){
//当前标签和父亲标签的下一个标签的第一个标签
//$(doc).parent().next().first().text('0000')
temp = '<p>' + v.username + ':' + v.content + '---' + v.create_date + '</p>';
//这里找到.reply的CSS,先清除当前的内容,不然会出现重复,这样只会显示最新的内容,正常要放到循环外面
//$(doc).parent().next().find('.replys').empty();
//这里找到.reply的CSS,再将返回的数据插进去
$(doc).parent().next().find('.replys').append(temp);
});
//这里点击时会去掉当前的hide的CSS
$(doc).parent().next().toggleClass('hide');
}
}
}
function Submit(doc,id){
//上一个标签
var value = $(doc).prev().val();
//提交后清除输入框
$(doc).prev().val('');
$('#shade,loading').removeClass('hide');
$.ajax(){
url:'/submitreply/',
type:'POST',
data:{nid:id,data:value},
sussess:function(callback){
//callback是后台返回的数据
console.log(callback;)
var callback = jQuery.parseJSON(callback);
if (callback.status==1){
//把数据Append到回复列表中
temp = '<p>' + callback.data.username + ':' + callback.data.content + '---' + callback.data.create_date + '</p>';
$(doc).parent().prev().append(temp)
//底下两行代码可以让评论数实时的更新,添加一条时自动计数
//先提交到后台,正常保存后自动加1,同时将新的内容和数值提交到前台
count = '评论' + callback.data.reply_count
$(doc).parent().parent().prev().find('.reply').text(count)
}else{
alert('失败')}
}
$('#shade,loading').addClass('hide');
}
}
function SendMsg(){
/*
简单的写法
获取Message的内容
var value = $('#message').val()
将内容添加到Pool中
$('#chatpool').append(value)
*/
//正常思路:将要发的内容通过Ajax发送到后台存放到数据库中
//再从数据库获取时间/内容/用户返回给前台
var value = $('#message').val()
value = $('#message').val('')
$.ajax({
url:'/subchat/',
data:{data:value},
type:'POST',
success:function(callback){
var callback = jQuery.parseJSON(callback);
if(callback.status == 1){
var now = callback.data.create_date;
var name = callback.data.username;
//这里定义的ID是为了后续取数据时,系统会生成两条同样的数据,定义了最后的ID后,就更新的下面getchat2中的ID
window.last_id = callback.data.id;
var template ='<div><div>'+name+'---'+now+'</div>'+value+'</div>'
$('#chatpool').append(template) ;
//先用DOM获取scroll的高度
var height = document.getElementById('chatpool').scrollHeight();
//再将scrollTop设置为离顶部这么高,这样就让流动条在最下面
$('#chatpool').scrollTop(height);
}else{
alert('请求异常。');
}
}
})
}
setInterval('going()',2000)
window.is_first = true
function going(){
if(window.is_first){
$.ajax({
url:'/getchart/',
type:'POST',
success:function(callback){
console.log(callback);
callback = jQuery.parseJSON(callback);
callback = callback.reverse()
window.last_id = callback[0].id
$.each(callback,function(k,v){
var now = v.create_date;
var name = v.user__username;
var value = v.content
var template ='<div><div>'+name+'---'+now+'</div>'+value+'</div>'
$('#chatpool').append(template)
});
window.is_first = false;
//先用DOM获取scroll的高度
var height = document.getElementById('chatpool').scrollHeight()
//再将scrollTop设置为离顶部这么高,这样就让流动条在最下面
$('#chatpool').scrollTop(height)
}
});
}else{
$.ajax({
url:'/getchart2/',
type:'POST',
data:{lastid:window.last_id}
success:function(callback){
console.log(callback);
callback = jQuery.parseJSON(callback);
if(callback.length>0){
window.last_id = callback[callback.length-1].id
$.each(callback,function(k,v){
var now = v.create_date;
var name = v.user__username;
var value = v.content
var template ='<div><div>'+name+'---'+now+'</div>'+value+'</div>'
$('#chatpool').append(template)
});
}
//先用DOM获取scroll的高度
var height = document.getElementById('chatpool').scrollHeight()
//再将scrollTop设置为离顶部这么高,这样就让流动条在最下面
$('#chatpool').scrollTop(height)
}
})
</script>
后台:
-----------------------------------------------------------------------------------
def subchat(request):
ret = {'status':0,'data':'','message':''}
try:
value = request.POST.get('data')
userobj = Admin.objects.get(id=request.session['current_user_id'])
chatobj = Chat.objects.create(content=value,user=userobj)
ret['status'] = 1
ret['data']= {'id':chatobj.id,
'username':userobj.username,
'content':chatobj.content, #这个可以不用返回,前端自己就可以获取
'create_date':chatobj.create_date.strftime('%Y-%m-%d %H:%M:%S')}
except Exception,e:
ret['message'] = e.message
return HttpResponse(json.dumps(ret))
#用于Jason序列化时间格式
class CJsonEncoder(json.JSONEncoder):
def default(self,obj):
if isinstance(obj,datetime.datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(obj,date):
return obj.strftime('%Y-%m-%d')
else:
return json,JSONEncoder.default(self,obj)
#用于前台点击评论时显示当前新闻的评论内容
def getreply(request):
id = request.POST.get('nic')
#这里可直接用外键__字段获取另一张表的内容 user__username new__id
reply_list = Reply.objcects.filter(new__id=id).values('id','content','user__username','create_date')
#json 无法序列化一个时间,可用serializers来操作
#serialize(format, queryset, **options)
'''
reply_list = serializers.serialize('json', reply_list)
return HttpResponse(reply_list)
'''
#用自己定义的类来处理时间格式
reply_list = list(reply_list)
reply_list = json.dumps(reply_list,cls=CJsonEncoder)
return HttpResponse(reply_list)
#用于前台提供评论内容
def getchart(request):
chatlist = Chat.objects.all().order_by('-id')[0:10].values('id','content','user__username','create_date')
chatlist = list(chatlist)
chatlist = json.dumps(chatlist,cls=CJsonEncoder)
return HttpResponse(chatlist)
def getchart2(request):
lastid = request.POST.get('lastid')
chatlist = Chat.objects.all().filter(id__gt=lastid).values('id','content','user__username','create_date')
chatlist = list(chatlist)
chatlist = json.dumps(chatlist,cls=CJsonEncoder)
return HttpResponse(chatlist)
作业:
-----------------------------------------------------------------------------------
评论样式更新
加上分页
装饰器使用,想评论可能弹跳出框,先登录,再发评论
自己可以写一个博客,将所有的内容放到上面
前台
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>louts bbs page</title>
<style>
.left{
float:left;
width:60%;
height:300px;
background-color:#fff;
border:solid 1px;
}
.right{
float:right;
width:30%;
height:300px;
background-color:#fff;
border:solid 1px;
}
.chat-content{
height:250px;
overflow: auto;
}
.input{
height:50px;
}
.pg-header {
height: 44px;
background-color: #de8001;
}
.pg-body {
width: auto;
overflow: hidden;
height: auto!important;
min-height: 713px;
padding: 6px 28px 60px;
background-color: #fff;
}
.head-content {
width: 1016px;
margin: 0 auto;
line-height: 44px;
position: relative;
}
.header-menu{
float:left;
margin-left:21px;
}
.digg-logo {
width: 121px;
height: 23px;
background: url(/static/images/logo.png) no-repeat 0 0;
float: left;
margin-top: 11px;
}
a.tb {
color: black;
margin-left: -3px;
padding: 0 13px 0 16px;
display: inline-block;
line-height: 44px;
}
a.tb:hover {
color: #red;
background-color:white;
}
a.active {
color: #red;
background-color:white;
}
</style>
</head>
<body>
<div class='pg-header'>
<div class='head-content'>
<a href="/" class="digg-logo"></a>
<div class='header-menu'>
<a href='/index' class='tb active'>全部</a>
<a href='/index' class='tb'>1024区</a>
<a href='/index' class='tb'>老男孩</a>
<a href='/index' class='tb'>IT民工</a>
</div>
<div>当前登录用户:{{user}} <a href='/logout/'>退出</a></div>
<div></div>
</div>
</div>
<div class='pg-body'>
<div class='left'></div>
<div class='right'>
<div id='chatpool' class='chat-content'></div>
<div class='input'>
<textarea id='content' rows="3" cols="30"></textarea>
<input type='button' value='提交' onclick='submit(this)'/>
</div>
</div>
</div>
<div class='pg-buttom'></div>
<script src='/static/jquery/jquery-1.8.0.js'></script>
<script type="text/javascript">
//这个函数是点击时触发一个Ajax的提交
function submit(doc){
//获取id为content的值
var value = $('#content').val();
//清空id为content
$('#content').val('');
$.ajax({
url:'/sendmsg/',
type:'POST',
data:{msg:value},
success:function(callback){
//Json反解析
var callback = jQuery.parseJSON(callback);
//根据后台返回的,如果是1,为正常
if(callback.status==1){
var username = callback.data.username;
var date = callback.data.create_date;
//定义全局的LastID,用来发送消息时更新最新ID,方便传递给下面函数
window.last_id = callback.data.id
var temp = '<div>'+username + '---'+date+'</div><div>'+value+'</div><br>'
//将得到的数据放添加到#chatpool里
$('#chatpool').append(temp);
//先用DOM获取scroll的高度
var height = document.getElementById('chatpool').scrollHeight()
//再将scrollTop设置为离顶部这么高,这样就让流动条在最下面
$('#chatpool').scrollTop(height)
}else{
alert(callback.message)
};
}
})
}
//设定一个定时器,每3秒执行一次
setInterval('going()',3000)
//设备一个全局变量,判断第一次执行时为True,以后则为False
window.first = true
//定义一个函数,当其他用户第一次登录时,显示最后的10条记录
function going(){
console.log(window.first);
if(window.first){
$.ajax({
url:'/getchat/',
type:'POST',
success:function(callback){
var callback = jQuery.parseJSON(callback);
window.last_id = callback[0].id;
var callback = callback.reverse();
$.each(callback,function(k,v){
var username = v.user__username;
var date = v.create_date;
var value = v.content;
var temp = '<div>'+username + '---'+date+'</div><div>'+value+'</div><br>'
$('#chatpool').append(temp);
});
window.first = false;
var height = document.getElementById('chatpool').scrollHeight;
$('#chatpool').scrollTop(height);
}
});
//当不是第一次访问时,根据最后的ID,来得到此ID后的数据
}else{
console.log(window.last_id);
$.ajax({
url:'/getchat2/',
type:'POST',
data:{lastid:window.last_id},
success:function(callback){
var callback = jQuery.parseJSON(callback);
if(callback.length>0){
//重新定义最后ID
window.last_id = callback[callback.length-1].id;
console.log(window.last_id);
console.log(callback);
$.each(callback,function(k,v){
var username = v.user__username;
var date = v.create_date;
var value = v.content;
var temp = '<div>'+username + '---'+date+'</div><div>'+value+'</div><br>'
$('#chatpool').append(temp);
});
var height = document.getElementById('chatpool').scrollHeight;
$('#chatpool').scrollTop(height);
}
}
});
}
}
</script>
</body>
</html>
后台
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render,render_to_response,HttpResponse, redirect
from models import *
import json
from django.core import serializers
from json.encoder import JSONEncoder
# Create your views here.
def index(request):
all_data = News.objects.all()
return render_to_response('index.html',{'data':all_data})
#用于点赞功能,点击时写到数据库中,并将数据返回给前台
def addfavor(request):
ret = {'status':0,'data':'','message':''}
try:
#这块有时会出现Sock错误error: [Errno 10053]
id = request.POST.get('id')
newsObj = News.objects.get(id=id)
temp = newsObj.favor_count + 1
newsObj.favor_count = temp
newsObj.save()
ret['status'] = 1
ret['data'] = temp
except Exception,e:
print 'error'
ret['message'] = '页面出错了'
print ret['message']
return HttpResponse(json.dumps(ret))
'''
#外键取数据可以用外键名称__id来操作,查询用点
#如果数据中有时间格式,Json无法序列化
#可使用Django的专用包来解决 serializers
#serializers.serialize(format, queryset)
#不能通过Reply('#reply_detail来访问Part4的内容,这样点击后会改变所有
#要通过子标签的父标签的下一个标签来找到$(doc).parent().netx()
$(doc).parent().next().first()找到子类第一个标签,可用Appen添加内容,
或ToggleClass来去掉CSS
Jquery用来迭代数据,obj是一个序列
$.each(obj,function(k,v){
temp = v.fields
})
'''
def login(request):
if request.methos == 'POST':
username = request.POST.get('usernmae')
password = request.POST.get('password')
try:
#currentObj得到是一个对象
currentObj = Admin.objects.get(username=username,
passsword=password)
except Exception,e:
currentObj = None
if currentObj:
request.session['current_user_id'] = currentObj.id
return redirect('/index')
else:
return redirect('/login')
return render_to_response('login.html')
def submitreply(request):
ret = {'status':0,'data':'','message':''}
try:
id = request.POST.get('nid')
data = request.POST.get('data')
#获取新闻的对象
newsObj = News.objects.get(id=id)
obj = Reply.objects.create(content=data,
user=Admin.objects.get(id=request.session['current_user_id']),
new=newsObj)
#评论保存后同时要更新闻的评论条目,自动加1
temp = newsObj.reply_count + 1
newsObj.reply_count = temp
newsObj.save()
#将数量放到前端的字典中
ret['data']= {'reply_count':temp,'content':obj.content,
'user__name':obj.user.username,
'create_date':obj.create_date.strftime('%Y-%m-%d %H:%M:%S')}
ret['status'] = 1
except Exception,e:
ret['message'] = e.message
return HttpResponse(json.dumps(ret))
def subchat(request):
ret = {'status':0,'data':'','message':''}
try:
value = request.POST.get('data')
userobj = Admin.objects.get(id=request.session['current_user_id'])
chatobj = Chat.objects.create(content=value,user=userobj)
ret['status'] = 1
ret['data']= {'id':chatobj.id,
'username':userobj.username,
'content':chatobj.content, #这个可以不用返回,前端自己就可以获取
'create_date':chatobj.create_date.strftime('%Y-%m-%d %H:%M:%S')}
except Exception,e:
ret['message'] = e.message
return HttpResponse(json.dumps(ret))
#用于Jason序列化时间格式
class CJsonEncoder(json.JSONEncoder):
def default(self,obj):
if isinstance(obj,datetime.datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(obj,date):
return obj.strftime('%Y-%m-%d')
else:
return json,JSONEncoder.default(self,obj)
#用于前台点击评论时显示当前新闻的评论内容
def getreply(request):
id = request.POST.get('nic')
#这里可直接用外键__字段获取另一张表的内容 user__username new__id
reply_list = Reply.objcects.filter(new__id=id).values('id','content','user__username','create_date')
#json 无法序列化一个时间,可用serializers来操作
#serialize(format, queryset, **options)
'''
reply_list = serializers.serialize('json', reply_list)
return HttpResponse(reply_list)
'''
#用自己定义的类来处理时间格式
reply_list = list(reply_list)
reply_list = json.dumps(reply_list,cls=CJsonEncoder)
return HttpResponse(reply_list)
#用于前台提供评论内容
def getchat(request):
chatlist = Chat.objects.all().order_by('-id')[0:10].values('id','content','user__username','create_date')
chatlist = list(chatlist)
chatlist = json.dumps(chatlist,cls=CJsonEncoder)
return HttpResponse(chatlist)
def getchat2(request):
lastid = request.POST.get('lastid')
chatlist = Chat.objects.all().filter(id__gt=lastid).values('id','content','user__username','create_date')
chatlist = list(chatlist)
chatlist = json.dumps(chatlist,cls=CJsonEncoder)
return HttpResponse(chatlist)
浙公网安备 33010602011771号