Web微信

复制代码
 1 D:\soft\work\Python_17\day23\weixin>tree /F
 2 卷 NewDisk 的文件夹 PATH 列表
 3 卷序列号为 2E8B-8205
 4 D:.
 5 │  db.sqlite3
 6 │  manage.py
 7  8 ├─.idea
 9 │  │  misc.xml
10 │  │  modules.xml
11 │  │  weixin.iml
12 │  │  workspace.xml
13 │  │
14 │  └─inspectionProfiles
15 │          profiles_settings.xml
16 17 ├─statics
18 │  ├─css
19 │  │      bbs.css
20 │  │      bootstrap-select.min.css
21 │  │      bootstrap-theme.css
22 │  │      bootstrap-theme.css.map
23 │  │      bootstrap-theme.min.css
24 │  │      bootstrap-theme.min.css.map
25 │  │      bootstrap.css
26 │  │      bootstrap.css.map
27 │  │      bootstrap.min.css
28 │  │      bootstrap.min.css.map
29 │  │      bootstrapValidator.min.css
30 │  │
31 │  ├─fonts
32 │  │      glyphicons-halflings-regular.eot
33 │  │      glyphicons-halflings-regular.svg
34 │  │      glyphicons-halflings-regular.ttf
35 │  │      glyphicons-halflings-regular.woff
36 │  │      glyphicons-halflings-regular.woff2
37 │  │
38 │  └─js
39 │          bootstrap-select.js.map
40 │          bootstrap-select.min.js
41 │          bootstrap.js
42 │          bootstrap.min.js
43 │          bootstrapValidator.min.js
44 │          city_info.js
45 │          jquery-3.2.1.js
46 │          jquery-3.2.1.min.js
47 │          jquery.cookie.js
48 │          npm.js
49 50 ├─templates
51 │      contactList.html
52 │      index.html
53 │      login.html
54 55 ├─utils
56 │  │  get_sync_key.py
57 │  │  myResponse.py
58 │  │
59 │  └─__pycache__
60 │          get_sync_key.cpython-35.pyc
61 │          myResponse.cpython-35.pyc
62 63 ├─wechat
64 │  │  admin.py
65 │  │  apps.py
66 │  │  demo.py
67 │  │  models.py
68 │  │  tests.py
69 │  │  views.py
70 │  │  __init__.py
71 │  │
72 │  ├─migrations
73 │  │  │  __init__.py
74 │  │  │
75 │  │  └─__pycache__
76 │  │          __init__.cpython-35.pyc
77 │  │
78 │  └─__pycache__
79 │          admin.cpython-35.pyc
80 │          apps.cpython-35.pyc
81 │          models.cpython-35.pyc
82 │          views.cpython-35.pyc
83 │          __init__.cpython-35.pyc
84 85 └─weixin
86     │  settings.py
87     │  urls.py
88     │  wsgi.py
89     │  __init__.py
90 91     └─__pycache__
92             settings.cpython-35.pyc
93             urls.cpython-35.pyc
94             wsgi.cpython-35.pyc
95             __init__.cpython-35.pyc
96 
97 
98 D:\soft\work\Python_17\day23\weixin>
目录结构
复制代码

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# login.html
 
 
 
 
{% load staticfiles %}
 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 
 
<div>
    <img id="wx_pic" src="{{ img_url }}" style="height: 200px; width: 200px">
</div>
 
<script src="{% static "js/jquery-3.2.1.js" %}"></script>
<script>
 
    $(function () {
        checkLogin();
    });
     
    function checkLogin() {
        TIP = 0;
        console.log("checkLogin ... ");
        $.ajax({
            url: '/loginCheck.htm',
            type: 'GET',
            data: {'tip':TIP},
            success:function (data) {
                var data=JSON.parse(data);
                if('201' == data.code){
                    $("#wx_pic").attr('src',data.data);
                    checkLogin();
{#                    tip=0;#}
                }
                else if('200' == data.code){
                    location.href = '/index.htm';
                }
                else {
                    console.log(">>> "+data.code);
                    checkLogin();
                }
                console.log(typeof data);
                console.log(data);
            }
        })
    }
 
</script>
 
 
</body>
</html>

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# index.html
 
 
 
{% load staticfiles %}
 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
 
<h3>个人信息</h3>
<img src="/showAvatar.htm?img={{ init_dict.User.HeadImgUrl }}" alt="">
<ul>
    <li>{{ init_dict.User.NickName }}</li>
    <li>{{ init_dict.User.UserName }}</li>
    <li>{{ init_dict.User.Signature }}</li>
</ul>
 
<h3>最近联系人列表</h3>
<ul>
    {% for item in init_dict.ContactList %}
        <img src="/showAvatar.htm?img={{ item.HeadImgUrl }}" alt="">
        <li>{{ item.NickName }}</li>
        <li>{{ item.UserName }}</li>
        <li>{{ item.Signature }}</li>
    {% endfor %}
 
    <li><a href="/contactList.htm">查看所有联系人</a></li>
</ul>
 
 
 
 
<script src="{% static "js/jquery-3.2.1.js" %}"></script>
<script>
 
</script>
 
</body>
</html>

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# contactList.html
 
 
 
{% load staticfiles %}
 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static "css/bootstrap.css" %}">
    <script src="{% static "js/bootstrap.js" %}"></script>
 
</head>
<body>
 
<h3>发送消息...</h3>
{% csrf_token %}
<div class="input-group">
    <span class="input-group-addon" id="sizing-addon2">发送给谁</span>
    <input type="text" class="form-control" placeholder="请输入对方的id" aria-describedby="sizing-addon2" id="to_user">
</div>
<div class="input-group">
    <span class="input-group-addon" id="sizing-addon2">消息内容</span>
    <input type="text" class="form-control" placeholder="请输入要发送的内容" aria-describedby="sizing-addon2" id="msg">
</div>
<button id="btn" type="button" class="btn btn-success">发送</button>
<button id="logout" type="button" class="btn btn-info">退出登录</button>
 
<div class="private">
    <h3>个人信息</h3>
    <img src="/showAvatar.htm?img={{ init_dict.User.HeadImgUrl }}" alt="">
    <ul>
        <li>{{ init_dict.User.NickName }}</li>
        <li>{{ init_dict.User.UserName }}</li>
        <li>{{ init_dict.User.Signature }}</li>
    </ul>
</div>
 
<div class="contactList">
    <h3>联系人列表</h3>
    <ul>
        {% for user in contact_list_dict.MemberList %}
            <li>{{ user.UserName }}</li>
            <li>{{ user.NickName }}</li>
            <li>{{ user.RemarkName }}</li>
            <li>{{ user.Signature }}</li>
            <ul>
                <li>{{ user.Province }}</li>
                <li>{{ user.City }}</li>
            </ul>
        {% endfor %}
    </ul>
</div>
 
<script src="{% static "js/jquery-3.2.1.js" %}"></script>
<script src="{% static "js/jquery.cookie.js" %}"></script>
<script>
 
    $(function () {
        getMsg();
        bindBtnEvent();
        bindLogoutEvent();
    });
    function bindBtnEvent() {
        $("#btn").click(function () {
            $.ajax({
                url:'/sendMsg.htm',
                type:'POST',
                data:{'to_user':$("#to_user").val(),'msg':$("#msg").val()},
                headers:{'X-CSRFToken': $.cookie('csrftoken')},
                success:function (res) {
                    var data=JSON.parse(res);
                    if(0 == data.BaseResponse.Ret){
                        alert("消息发送成功!");
                    }else {
                        alert("消息发送失败:" + data.BaseResponse.ErrMsg);
                    }
                },
                error:function (res) {
                    console.log("[[ bindBtnEvent ]] raise err..." + res)
                }
            })
        })
    }
    function getMsg() {
        $.ajax({
            url:'/syncCheck.htm',
            type:'GET',
            success:function (res) {
                var data=JSON.parse(res);
                if(data.AddMsgCount > 0){
                    alert(data.AddMsgList);
                    for(var i=0; i<data.AddMsgCount; i++) {
                        alert("收到 " + data.AddMsgList[i].FromUserName + " 的新消息:" + data.AddMsgList[i].Content);
                    }
                }
                getMsg();
            },
            error:function (res) {
                console.log("[[ getMsg ]] raise err..." + res);
                getMsg();
            }
        })
    }
    function bindLogoutEvent() {
        $("#logout").click(function () {
            $.ajax({
                url:'/logout.htm',
                type:'GET',
                success:function (arg) {
                     
                }
            })
        })
    }
</script>
 
</body>
</html>

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# urls.py
 
 
 
from django.conf.urls import url
from django.contrib import admin
from wechat import views
 
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login.htm$', views.login),
    url(r'^loginCheck.htm$', views.loginCheck),
    url(r'^index.htm$', views.index),
    url(r'^showAvatar.htm$', views.showAvatar),
    url(r'^contactList.htm$', views.contactList),
    url(r'^sendMsg.htm$', views.sendMsg),
    url(r'^syncCheck.htm$', views.syncCheck),
    url(r'^logout.htm$', views.logout),
]

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# views.py
 
 
 
from django.shortcuts import render,HttpResponse,redirect
import re
import time
import json
import requests
from bs4 import BeautifulSoup
from utils.myResponse import BaseResponse
from utils.get_sync_key import get_sync_key
 
"""
微信网页版登录示例
 
GET        https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_=1508052025433
得到响应:   window.QRLogin.code = 200; window.QRLogin.uuid = "IapQqsoqcA==";
 
二维码src   https://login.weixin.qq.com/qrcode/IapQqsoqcA==
 
长轮询:     https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=IapQqsoqcA==&tip=0&r=-518626217&_=1508052025438
"""
 
def login(req):
    ctime = time.time() * 1000
    qrcode_url = "https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_={}".format(ctime)
    rsp1 = requests.get(url=qrcode_url)
    qrcode = re.findall('.uuid = "(.*)";', rsp1.text)[0]
    img_url = "https://login.weixin.qq.com/qrcode/{}".format(qrcode)
    req.session['qrcode'] = qrcode
    req.session['ctime'] = ctime
    return render(req,'login.html',{'img_url':img_url})
 
def get_pass_ticket(html):
    soup = BeautifulSoup(html, 'html.parser')
    ret = {}
    for tag in soup.find(name='error').find_all():
        ret[tag.name] = tag.text
    return ret
 
def loginCheck(req):
    """
    判断是否扫码;扫码之后立即进入下一次长轮询,等待用户点击确认登录
        window.code=408;    未扫码
        window.code=201;    已扫码
        window.userAvatar = 'data:img/jpg;base64,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';
        window.code=200;    已确认登录
        window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AZ3EYrgZt_xzrpgpevpgZdnN@qrticket_0&uuid=ochHx1cRew==&lang=zh_CN&scan=1508341438";
    :param req:
    :return:
    """
    res = BaseResponse()
    qrcode = req.session.get('qrcode')
    ctime = time.time()*1000
    tip = req.GET.get("tip")
    tip = tip if tip else 0
    print(qrcode, tip, ctime)
 
    url = "https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid={0}&tip={1}&r=-716232763&_={2}".format(qrcode,tip,ctime)
    rsp2 = requests.get(url=url)
 
    res.status = rsp2.status_code
    res.code = re.findall(".code=(\d+).",rsp2.text)[0]
    if '201' == res.code:
        avatar_str = re.findall("userAvatar = '(.*)'.",rsp2.text)[0]
        res.data = avatar_str if avatar_str else ""
    elif '200' == res.code:
        # 记录用户点击登录时候获得的cookies
        req.session['LOGIN_COOKIES'] = rsp2.cookies.get_dict()
        # 获取 redirect_uri
        redirect_uri = re.findall('redirect_uri="(.*)";', rsp2.text)[0]
        redirect_uri = redirect_uri + "&fun=new&version=v2"
        # 获取凭证
        rsp3 = requests.get(url=redirect_uri)
        ticket_dict = get_pass_ticket(rsp3.text)
        # 记录请求redirect_uri之后获取的 TICKET_DITC 以及 相应cookies
        req.session['TICKET_DITC'] = ticket_dict
        req.session['TICKET_COOKIES'] = rsp3.cookies.get_dict()
        res.data = rsp3.text
    else:
        res.data = rsp2.text
        print(res.dict_info)
    return HttpResponse(json.dumps(res.dict_info))
 
 
def index(req):
    if not req.session.get('TICKET_DITC'):
        return redirect('/login.htm')
 
    ticket_dict = req.session.get('TICKET_DITC')
    # 获取完TICKET_DITC之后开始获取最近联系人列表并初始化
    init_params_dict = {
        'BaseRequest': {
            'DeviceID': "e553172362037361",
            'Sid': ticket_dict['wxsid'],
            'Skey': ticket_dict['skey'],
            'Uin': ticket_dict['wxuin']
        }
    }
    url_post = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-809803709&pass_ticket={}".format(ticket_dict.get('pass_ticket'))
    rsp4 = requests.post(url=url_post, json=init_params_dict)
    rsp4.encoding='utf-8'  # 避免出现中文乱码
    print(">>>>>>>>  ", rsp4.text)
    # 记录初始化之后获取的cookies
    req.session['INIT_COOKIES'] = rsp4.cookies.get_dict()
    init_dict = json.loads(rsp4.text)
    sync_key = init_dict.pop('SyncKey') # sync_key 用于在后面发送消息
    # 记录拿到的初始化信息,后面需要展示在页面上,所以先存储在session里
    req.session['init_dict'] = init_dict
    req.session['sync_key'] = sync_key
    return render(req,'index.html',{'init_dict':init_dict})
 
def showAvatar(req):
    # 整合cookies
    all_cookies = {}
    LOGIN_COOKIES = req.session.get('LOGIN_COOKIES')
    TICKET_COOKIES = req.session.get('TICKET_COOKIES')
    INIT_COOKIES = req.session.get('INIT_COOKIES')
    all_cookies.update(LOGIN_COOKIES)
    all_cookies.update(TICKET_COOKIES)
    all_cookies.update(INIT_COOKIES)
    # 获取前端传过来的头像参数并拼接头像url
    img_prefix = req.GET.get('img')     # /cgi-bin/mmwebwx-bin/webwxgeticon?seq=1576406163
    username = req.GET.get('username')  # @c1c38ffccbf118f6f62a023364f624c1bf683d3dc4432ad0203520b5f63f2742
    skey = req.GET.get('skey')          # @crypt_af096eac_6563c98d6143e21bcd2911bfdb3c2c50
    avatar_url = "https://wx.qq.com{0}&username={1}&skey={2}".format(img_prefix,username,skey)
    rsp = requests.get(url=avatar_url,cookies=all_cookies)
    return HttpResponse(rsp.content)
 
def contactList(req):
    # 整合cookies
    all_cookies = {}
    LOGIN_COOKIES = req.session.get('LOGIN_COOKIES')
    TICKET_COOKIES = req.session.get('TICKET_COOKIES')
    INIT_COOKIES = req.session.get('INIT_COOKIES')
    all_cookies.update(LOGIN_COOKIES)
    all_cookies.update(TICKET_COOKIES)
    all_cookies.update(INIT_COOKIES)
 
    ctime = time.time()
    TICKET_DITC = req.session.get('TICKET_DITC')
    pass_ticket = TICKET_DITC.get('pass_ticket')
    skey = TICKET_DITC.get('skey')
    url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket={0}&r={1}&seq=0&skey={2}".format(pass_ticket,ctime,skey)
    rsp = requests.get(url=url,cookies=all_cookies)
    rsp.encoding = 'utf-8'  # 避免出现中文乱码
    contact_list_dict = json.loads(rsp.text)
    print(">>>>>>>>>>>>>>>>>\n", contact_list_dict)
    # 把所有联系人信息存储到session里
    req.session['contact_list_dict'] = contact_list_dict
    init_dict = req.session.get('init_dict')
    return render(req,'contactList.html',{'contact_list_dict':contact_list_dict,'init_dict':init_dict})
 
def sendMsg(req):
    ctime = time.time() * 1000
    to_user = req.POST.get('to_user')
    msg = req.POST.get('msg')
    from_user = req.session.get('init_dict').get('User').get('UserName')
    print("++++++++++++++++++++++++++++++++++")
    print(to_user,msg)
    ticket_dict = req.session.get('TICKET_DITC')
    pass_ticket = ticket_dict.get('pass_ticket')
    send_msg_url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?pass_ticket={0}".format(pass_ticket)
    msg_dict = {
        'BaseRequest':{
            'DeviceID': "e553172362037361",
            'Sid': ticket_dict['wxsid'],
            'Skey': ticket_dict['skey'],
            'Uin': ticket_dict['wxuin']
        },
        'Msg':{
            'ClientMsgId':ctime,
            'Content':msg,
            'FromUserName':from_user,
            'LocalID':ctime,
            'ToUserName':to_user,
            'Type':1
        },
        'Scene':0
    }
    # 整合cookies
    all_cookies = {}
    LOGIN_COOKIES = req.session.get('LOGIN_COOKIES')
    TICKET_COOKIES = req.session.get('TICKET_COOKIES')
    INIT_COOKIES = req.session.get('INIT_COOKIES')
    all_cookies.update(LOGIN_COOKIES)
    all_cookies.update(TICKET_COOKIES)
    all_cookies.update(INIT_COOKIES)
 
    # 下面这种方式发送会出现中文乱码:
    # rsp = requests.post(url=send_msg_url, json=msg_dict, cookies=all_cookies)
    """
        json序列化的时候是可以加参数的:
 
        data = {
            'name':'alex',
            'msg':'中文asa'
        }
        import json
        print(json.dumps(data))
        按Unicode显示:  {"msg": "\u4e2d\u6587asa", "name": "alex"}
         
        print(json.dumps(data,ensure_ascii=False))
        按中文显示:      {"msg": "中文asa", "name": "alex"}
         
        json.dumps() 之后是字符串
        requests.post() 默认是按照 latin-1 编码,不支持中文
        所以改成直接发bytes:
        requests.post(data=json.dumps(data,ensure_ascii=False).encode('utf-8'))
    """
    rsp = requests.post(
        url=send_msg_url,
        data=json.dumps(msg_dict,ensure_ascii=False).encode('utf-8'),
        headers={'Content-Type':'application/json; charset=utf-8'},
        cookies=all_cookies
    )
    rsp.encoding = 'utf-8'  # 避免出现中文乱码
    ret_dict = json.loads(rsp.text)  # 将字符串转换成字典对象,这样前端接收的时候就能使用 xx.xx 形式进行取值了
    return HttpResponse(json.dumps(ret_dict))
 
 
def syncCheck(req):
    # 整合cookies
    all_cookies = {}
    LOGIN_COOKIES = req.session.get('LOGIN_COOKIES')
    TICKET_COOKIES = req.session.get('TICKET_COOKIES')
    INIT_COOKIES = req.session.get('INIT_COOKIES')
    all_cookies.update(LOGIN_COOKIES)
    all_cookies.update(TICKET_COOKIES)
    all_cookies.update(INIT_COOKIES)
 
    ctime = time.time() * 1000
    ticket_dict = req.session.get('TICKET_DITC')
    pass_ticket = ticket_dict.get('pass_ticket')
    sync_key = req.session.get('sync_key')
    sync_check_url = "https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck"
    params = {
        'r':ctime,
        'skey':ticket_dict.get('skey'),
        'sid':ticket_dict.get('wxsid'),
        'uin':ticket_dict.get('wxuin'),
        'deviceid':'e553172362037361',
        'synckey':get_sync_key(sync_key)
    }
    # 检测是否有新消息到来
    rsp = requests.get(url=sync_check_url,params=params,cookies=all_cookies)
    print(rsp.text)
    # 去服务器端取回新消息
    if 'window.synccheck={retcode:"0",selector:"2"}' in rsp.text:
        data = {
            'BaseRequest':{
                'DeviceID': "e553172362037361",
                'Sid': ticket_dict['wxsid'],
                'Skey': ticket_dict['wxsid'],
                'Uin': ticket_dict['wxuin']
            },
            'SyncKey':sync_key,
            'rr':'-1324973514'
        }
        sync_msg_url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid={0}&skey={1}&pass_ticket={2}".format(ticket_dict['wxsid'],ticket_dict['wxsid'],pass_ticket)
        msg_res = requests.post(url=sync_msg_url,json=data,cookies=all_cookies)
        msg_res.encoding = 'utf-8'
        msg_res_dict = json.loads(msg_res.text)  # 将字符串转换成字典对象,这样前端接收的时候就能使用 xx.xx 形式进行取值了
        new_sync_key = msg_res_dict.get('SyncKey')  # 每次同步完新消息后,sync_key都会更新,所以每次记得重新获取并存储到session里
        req.session['sync_key'] = new_sync_key
        for msg in msg_res_dict.get('AddMsgList'):
            print(msg.get('FromUserName'),msg.get('CreateTime'),msg.get('Content'))
        return HttpResponse(json.dumps(msg_res_dict))
    else:
        return HttpResponse(json.dumps({'AddMsgCount':0,'AddMsgList':None}))
 
def logout(req):
    print("ByeBye...")
    req.session.clear()
    return redirect('/login.htm')

  

1
2
3
4
5
6
7
8
9
10
# get_sync_key.py
 
 
 
def get_sync_key(sync_key):
    sync_key_list = []
    for item in sync_key.get('List'):
        tmp = "%s_%s" % (item.get('Key'),item.get('Val'))
        sync_key_list.append(tmp)
    return "|".join(sync_key_list)

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# myResponse.py
 
 
class BaseResponse(object):
    def __init__(self):
        self.status = None
        self.code = None
        self.data = None
 
    @property
    def dict_info(self):
        return self.__dict__
 
 
class LikeResponse(BaseResponse):
    def __init__(self):
        self.msg = None
        super(LikeResponse, self).__init__()
 
 
if __name__ == '__main__':
    like = LikeResponse()
    print(like.dict_info)

  

 

posted @   RainingInMacondo  阅读(912)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示