概述
紫荆之声代码阅读之userpage
urls.py
在此文件里加入了一些url的patterns,其作用是使用将对应的正则表达式将url匹配到某一个view函数,并传递一定的参数。其中patterns这个函数的第一个参数是一个字符串,其含义是:后面url列表中view函数若有共同前缀,如此文件中view函数们都有共同前缀“userpage.views.”,那么就可以把第一个参数设为“’userpage.views’”(注意最后一个.不需要写),然后后面的view函数们的共同前缀就可以省略了,比如“'userpage.views.validate_post'”可以写成“'validate_post'”,所以第一个参数是用来少些重复路径的。可惜的是,上一届的代码中没有利用好这个功能,仅将第一个参数设为空字符串。
下面解释一下url函数的功能,拿以下一行为例:
url(r'^validate/(?P<openid>S+)/$', 'userpage.views.validate_view')
其中url的第一个参数是正则表达式,匹配模式中:^xxx表示以xxx开头,而xxx$表示以xxx结尾,如果是^xxx$就是精确匹配xxx。正则表达式中需要特别解释的是“?P<openid>”表示的是的是将尖括号后的匹配内容赋给变量openid,调用userpage.views.validate_view时就将此内容传给其同名的参数openid;在这里匹配的模式是“S+”表示的是一切不含空格的非空字符串。比如有个url是“validate/user123/”就会匹配调用userpage.views.validate_view且给该view函数传参,将名为openid的参数赋值为字符串’user123’。
safe_reverse.py
这个文件用于返回不同的view函数的url地址。其中SITE_DOMAIN是网页域名的字符串,在queryhandler.settings中定义了,为'http://tuan.ssast.org',任何url以此域名开头。
而后的具体路径部分的字符串生成,用到了reverse这个函数。为什么叫reverse呢?我们上一小节说到了patterns可以将url匹配,调用某view函数;而现在reverse函数是反过来的,根据view函数的函数名反过来得到其对应url的字符串。其中reverse会在当前线程的url配置文件中寻找反向匹配,在这里url配置文件就是urls.py。
下面具体解释一下reverse函数的用法,拿以函数s_reverse_validate(openid)为例:
reverse('userpage.views.validate_view', kwargs={'openid': openid})
其中第一个参数为view函数的函数名,第二个参数kwargs表示将正则表达式中形如“(?P<xxx>yyy)”的变量反向填充。如{'openid': openid}的openid是外层函数s_reverse_validate的参数,而’openid’字符串表示,将此参数反向填充到正则表达式“^validate/(?P<openid>S+)/$”中的名为<openid>的变量用openid替代。比如若openid为user456,那么该reverse函数的返回值就是“validate/user456/”。
值得一提,reverse函数存在的意义在于,在匹配url与view函数时能正向与逆向匹配都联动起来,如果以后某view函数的url有变动,只需改动urls.py一个文件中正向匹配的正则表达式即可,无需改动safe_reverse.py中逆向匹配的代码。
views.py
此文件是核心文件,用于定义一些view函数,最终返回给用户不同的html页面,而且返回的html页面是根据用户request的内容来生成的一些templates(模板)实例。
home
从最简单的home函数讲起:
def home(request):
return render_to_response('mobile_base.html')
就是返回templates文件夹中的“mobile_base.html”文件。由于此html模板中没有任何变量参数,所以可以如此简单地完成工作,render_to_response函数的功能就是根据第一个参数名来返回一个HttpResponse的对象,在这里也就是紫荆之声主页的html页面。
下面我们再来详细地分析几个函数。
validate_view
def validate_view(request, openid): #openid是用户微信号id
if User.objects.filter(weixin_id=openid, status=1).exists():
isValidated = 1 #filter函数类似数据库select/where操作,如果用户列表中存在
#微信号为openid的用户,且status=1即已认证,那么设置
#isValidated为1,否则为0。
else:
isValidated = 0
studentid = '' #默认初始化学生id为空串
if request.GET: #如果request是个GET请求,则从request中获取studentid对象的值赋给studentid变量,如果request中没有这个对象则赋空串(第二个参数)
studentid = request.GET.get('studentid', '')
#下面的代码是返回validation.html页面,而且使用的是模板生成的实例,其中html模板使用的4个变量的值都已在花括号中给出,冒号前是变量名,冒号后是值。
return render_to_response('validation.html', {
'openid': openid,
'studentid': studentid,
'isValidated': isValidated,
'now': datetime.datetime.now() + datetime.timedelta(seconds=-5),
}, context_instance=RequestContext(request))
以上注释已将代码功能解释得很清楚,validate_view函数主要的作用就在于返回用户认证页面validation.html,且根据用户的微信号判断用户是否已经认证过、request的get中是否有学生id等信息,返回不一样的页面。
validate_through_learn
这个函数能通过清华网络学堂的某个url来确认用户是不是清华账号,进而返回认证是否成功。具体代码分析如下:
def validate_through_learn(userid, userpass): #两个参数分别是清华账号的用户名与密码
req_data = urllib.urlencode({'userid': userid, 'userpass': userpass, 'submit1': u'登录'.encode('gb2312')}) #编码url请求包的格式,包括用户名、密码、请求类型(登录)
request_url = 'https://learn.tsinghua.edu.cn/MultiLanguage/lesson/teacher/loginteacher.jsp' #网络学堂验证登录的url地址,是一个jsp文件,必须要用户名、密码正确才能获得
req = urllib2.Request(url=request_url, data=req_data) #再次编码请求包
res_data = urllib2.urlopen(req) #给网络学堂发送上面的request请求
try:
res = res_data.read() #读取网络学堂返回的文件
except:
return 'Error'
if 'loginteacher_action.jsp' in res: #如果返回文件中有loginteacher_action.jsp,证明用户名、密码正确,于是用户验证成功!否则就验证失败!
return 'Accepted'
else:
return 'Rejected'
具体代码的含义以上注释已解释得十分清楚。换言之,这个函数就是根据用户提供的清华网络账号和密码,验证其是否确实是清华账户的一个接口。
validate_post
这个函数是用于用户认证的,也就是微信号和清华账号的绑定,进而更新数据库;该函数将绑定到认证页面Form表单的action目标中。需要注意的是函数考虑了多种情况,例如一个清华用户的绑定微信号变更的情况、新用户绑定微信号情况;原则是数据库中清华账号id都是唯一的,而绑定微信号可变更。具体代码如下:
def validate_post(request):
#要求request是POST类型的,且包含微信号、清华账号、密码等信息
#具体的请求发送在认证页面validation.html的js文件validation.js中完成
if (not request.POST) or (not 'openid' in request.POST) or
(not 'username' in request.POST) or (not 'password' in request.POST):
raise Http404
userid = request.POST['username']
if not userid.isdigit(): #检查清华账号是不是纯数字,防错误输入
raise Http404
userpass = request.POST['password'].encode('gb2312')
validate_result = validate_through_learn(userid, userpass) #利用网络学堂进行清华账号验证,把验证结果返回
if validate_result == 'Accepted': #如果验证成功,那么开始绑定微信号
openid = request.POST['openid']
try:
#将原清华用户、原微信号的绑定状态清空,这里包含了微信号改绑定
#以及清华账号改绑定的状况,status=0表示账号存在但未认证(未绑定)
#的状态。
User.objects.filter(stu_id=userid).update(status=0)
User.objects.filter(weixin_id=openid).update(status=0)
except:
return HttpResponse('Error')
try:
#这里开始尝试更改绑定,考虑的是清华账号以前验证过一次,现在更改
#绑定微信号的情况,如果有异常,证明不存在stu_id=userid的数据项,
#证明清华账号从未验证过,跳到后面except的异常处理块中。
currentUser = User.objects.get(stu_id=userid)
currentUser.weixin_id = openid
currentUser.status = 1
try:
currentUser.save()
except:
return HttpResponse('Error')
except:
#如果跳到这一块,证明该清华账号从未验证过,于是在数据库中新建
#一项,来绑定清华账号与微信号。
try:
newuser = User.objects.create(weixin_id=openid, stu_id=userid, status=1)
newuser.save()
except:
return HttpResponse('Error')
return HttpResponse(validate_result) #不论清华账号验证成功与否,都返回验证结果
代码的具体含义在注释中已详尽解释。
有了以上几个函数的详细分析示例,我们对于controller文件的函数的操作都有了成熟的理解,那么剩下一些views函数就能很流程地解读,关于具体代码的走读,作者就不再赘述,只将其它views函数的功能列举一下。
其它views函数
details_view(request, activityid):根据activityid活动id来返回一个活动详情页面,函数首先会从Activity的model里找到该活动项,然后将活动项的信息提取出来,准备传给html模板生成实例。值得注意的是活动摘要部分,是活动介绍文字或其256字节的前缀,目的是防止介绍文字过长;另外会根据现在的系统时间判断活动是处于抢票前、抢票中还是抢票结束后,给状态变量赋予不同的值,html模板就会根据此值来生成不同的html页面。
ticket_view(request, uid):根据uid票据的唯一id返回票据页面,函数首先会从Ticket的model里利用filter函数找到该票据,然后提取其具体信息,判断当前活动是否已取消或已结束等状态,然后将这些信息都传给html模板,返回html页面实例。
help_view(request):返回帮助页面的html文件。
activity_menu_view(request, actid):根据actid活动id来返回活动的节目单页面。
helpact_view(request):返回关于活动的命令的帮助页面。
helpclub_view(request):返回关于社团的命令的帮助页面。
helplecture_view(request):返回关于讲座的命令的帮助页面。
templates & static
templates文件夹,里面存放了html模板。各html页面对应的views函数都能在views.py中找到,只要看每个views函数的render_to_response调用中第一个参数,就知道哪个views函数调用了哪个模板,从而可以根据上一章节的介绍找到对应页面的功能。
static里存放了一些html页面(模板)需要用到的css文件、img图片文件,以及各种js文件。
由于templates文件夹和static中与页面相关的文件比较多,js文件也相当复杂,再次不再赘述。只需知道,不同的页面模板能根据用户的请求生成一个具体的页面实例,而且每个页面有大量的js函数辅助完成各页面的具体交互与功能。
需要特别说明的是模板中的一些语法:
{{xxx}}:用双层花括号括起的是变量,这些变量是从views函数哪里传递而来的。
{%xxx%}:用花括号加百分号括起来的是模板语句。例如static关键字是产生static文件夹的路径;url关键字是将对应的views函数转换成为url地址;而block关键字比较关键,我们可以看到大量的形如{% block aaa %}xxx{% endblock %},其中aaa表示block块的名字,xxx为块的内容,我们可以看到不少html模板(如activitydetails.html)开头有一句extends语句(如{% extends "mobile_base.html" %}),意思是activitydetails.html是从mobile_base.html扩展而来的,然后能看到activitydetails.html文件里有很多block语句,且同名的block在mobile_base.html中也出现了,则生成activitydetails.html实例时会将mobile_base.html中同名的block内容换成activitydetails.html中的block内容,然后返回经过这样“拓展”后的mobile_base.html实例;include关键字则是在某处插入一个文件 (如html文件)。
最后
以上就是飞快啤酒为你收集整理的紫荆之声代码阅读之userpage紫荆之声代码阅读之userpage的全部内容,希望文章能够帮你解决紫荆之声代码阅读之userpage紫荆之声代码阅读之userpage所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复