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) |
作者:Standby — 一生热爱名山大川、草原沙漠,还有我们小郭宝贝!
出处:http://www.cnblogs.com/standby/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://www.cnblogs.com/standby/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步