利用Django做项目遇到的坑
引言
最近在用Django开发一个商城项目,第一次用这种语言来进行开发,凭借自己薄弱的MVC(在Django叫MTV)知识,以及不断地查Stack Overflow(感觉国内相关的博客比Java少多了),还是勉强地开发出来了,其实最科学的方法是查Django的开发手册(但是我英文不太好hhh),现在谈谈自己踩过的坑。
1、在models中filter和get的区别
当我们要从某个模型(model)中取出特定条件的数据的时候,可以采用这两种方法
queryset = models.Commodity.objects.filter(cid=com_id)
v = models.Village.objects.get(vid=vid)
先观察他们的结果:
他们的不同之处在于:filter()获得的是一个QuerySet,当符合条件的有多条数据的话,也会将这些数据全部存入QuerySeet,当数据不存在,返回空的QuerySet
缺点:要取出里面的对象的值非常麻烦
而get()获得的是一个实体对象,当符合条件的有多条数据的话或者数据不存在,会报错,
优点:可以直接取出对象的值,如 vid = v.vid
2、simplejson输出的中文被转成ASCII码的解决办法
由于后端的接口都是通过JSON来返回数据的,所以Python中的simplejson工具显得十分重要,但是初次使用出现这种情况
这是由于中文被转化成ASCII码了,所有我们的结果中含有中文的时候,请记得加上
json_data = simplejson.dumps(queryset, ensure_ascii=False)
3、当接口用POST方法的时候,用POSTMAN等工具调试总是提示“403”错误
出现这样的问题,其实是因为Django有自己的csrf防御机制,我们可以假设这样一个情景:
1.用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
3.用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
4.网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
5.浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
好了跑题了,我们那我们要进行测试应该怎么解决这个问题呢?就是在方法前加上注解
@csrf_exempt,来取消csrf的防御
4、当我们要取出values_list里面的内容要怎么做
olist=list(models.Order.objects.filter(user_id=openid).values_list('oid','total','date','address_id'))
我已经提前把它转化为list,可以通过断点看出:
它的外部是个list,内部是个tuple(元组),根据数据结构的知识(不懂百度下),我们可以遍历把他们都取出来,具体代码如下:
olen = len(olist)
for i in range(olen):
oid = olist[i][0]
total = olist[i][1]
date = olist[i][2]
address_id = olist[i][3]
注意:循环条件不能写成range[0:olen],否则会报错:“olen不是可以遍历的”
结果如下:
总结:value_list获得的就是一个里面分别装有tuple的queryset
5、获取request中POST方法传来的JSON
之前想通过表单的方式传来数据,但是一直不成功,代码如下:
oid = request.POST.get("oid")
后来决定用JSON来传输,也比较符合现在互联网的规则,那么后台怎么解析呢,主要还是用simplejson,具体代码如下,仅供参考:
try:
if request.method == 'POST':
req = simplejson.loads(request.body)
'''
从JSON数组中获取一系列的参数
'''
openid = req['openid']
area = req['area']
detail = req['detail']
name = req['name']
phone = req['phone']
except Exception:
import sys
info = "%s || %s" % (sys.exc_info()[0], sys.exc_info()[1])
dict['message'] = info
dict['create_at'] = str(ctime())
json = simplejson.dumps(dict)
6、注意Python2.7和Python3.5的包
举一个简单点的例子,当我用到了urlib来进行网络连接请求的时候,由于本机用了Python3.5,服务器的却是Python2.7(蛋疼),然后部署上去就有各种bug了,在Python2.7中,代码如下:
def connect(url):
req = urllib2.Request(url)
result = urllib2.urlopen(req)
res = result.read()
return res
在Python3.5中,代码如下:
def connect(url):
req = urllib.request.Request(url)
result = urllib.request.urlopen(req)
res = result.read()
return res
7、输出的JSON带有\
这个问题和前面的中文乱码不一样,这里要搞清楚simplejson的最基础一点:dumps方法是将元素转换成一个JSON格式的str(字符串),而loads方法则是读取json使之变成一个dict对象
下面请看代码:
json_add = simplejson.dumps({"area": area, "detail": detail, "name": name,"phone": phone},ensure_ascii=False)
aresult = json.loads(json_add)
对于dict对象,我们可以用append方法来进行字典元素的拼接