由于新APP需要服务端
就使用Django进行构建
API则使用Django rest framework
使用两个月过程中踩坑无数
也暴露出Django rest framework和Django自身诸多问题
1、文档不全面
Django Queryset使用起来非常方便
但遇到一些高等查询,如联表、排序等
就出现了很多文档不全、文档缺失的情况
在解决使用Django Queryset联表查询后
紧接着又遇到Django rest framework不支持Queryset.Values()序列化的问题
所以当你需要使用两者一同构建服务端时
难免需要根据自身需求完成一部分代码
2、rest framework细微的语言习惯不同
在Django里,用__符号表现联表查询
而在rest framework序列化里,使用传统的.来代表联表下一级
相对而言,rest framework更pythonic一点
但却在此造成了与Django ORM之间的语言障碍
若不详细阅读两边的开发文档
很容易在一些小细节上浪费过多时间
所以还是建议详细阅读相关功能的文档
https://docs.djangoproject.com/
3、复杂应用举例:电影搜索
关于在使用Django搜索,按关键词分词词序、分词匹配度排序的方法demo
#生成词序权重的方法,这边写了最多3层组合,太多分词则忽略,注重用户输入时前面3个分词,如:贫穷贵公子周渝民台湾版→贫穷 公子 周渝民 台湾,只取【贫穷 公子 周渝民】的组合
def segListQDict(segList,max=3):
from itertools import combinations
l=((len(segList)<=max) and len(segList)) or max
d={}
count=0
for x in range(l):
combins = [c for c in combinations(range(l), l-x)]
dic={}
if combins!=[()]:
for item in combins:
if len(item)!=1:
dic[count]=Q()
for i in item:
dic[count]=dic[count]&(Q(v_name__icontains=segList[i])|Q(v_yanyuan__icontains=segList[i]))
else:
dic[count]=Q(v_name__icontains=segList[item[0]])|Q(v_yanyuan__icontains=segList[item[0]])
d[count]=dic[count]
count += 1
return d
def cutKeyword(keyword,segList,keywordQ=Q(),orderBy='-v_id'):
#keyword为搜索关键词,segList为分词后的list
if keyword:
# 用户使用符号强分割关键词情况,如用户输入符号,在segList里也会被强分词
for k in keyword.split(' '):
# 这里使用and相关,加强用户使用空格分词视,搜索的优先级
keywordQ = keywordQ & Q(v_name__icontains=k)
# 保留词序权重
dic=segListQDict(segList)
# 结巴进行分析使用or或关系并入keywoedQ
otherQ = Q()
for seg in segList:
#关键词中如果有特定的分类词组则提取后进入排序kDict字典
seg, kDict = changeKeyword(seg)
if kDict != {}:
#关键词中是否包含类型,比如美剧铁拳,则拆分后,将美剧列入排序top2Q
otherQ = otherQ | Q(**clearDict(expendTypeID(kDict)))
if len(seg)>1:
keywordQ = keywordQ | Q(v_name__icontains=seg) | Q(v_yanyuan__icontains=seg)
# 分词结果排序
top1Q=Q(v_name=keyword)
top2Q=Q(v_name__icontains=keyword)|Q(v_yanyuan__icontains=keyword)|otherQ
if len(segList)>2:
#具体case when then方法可以参照Django文档,楼主尝试使用replace方法失败后转而使用then
orderBy=Case(
When(condition=top1Q, then=0),
When(condition=top2Q, then=1),
When(condition=Q(dic[0]), then=2),
When(condition=Q(dic[1]),then=3),
When(condition=Q(dic[2]), then=4),
When(condition=Q(dic[3]), then=5),
When(condition=Q(dic[4]), then=6),
When(condition=Q(dic[5]), then=7),
When(condition=Q(dic[6]), then=8),
default=10)
elif len(segList)==2:
orderBy = Case(
When(condition=top1Q, then=0),
When(condition=top2Q, then=1),
When(condition=Q(dic[0]), then=2),
When(condition=Q(dic[1]), then=3),
When(condition=Q(dic[2]), then=4),
default=10)
elif len(segList)==1:
orderBy = Case(
When(condition=top1Q, then=0),
When(condition=top2Q, then=1),
When(condition=Q(dic[0]), then=2),
default=10)
return keywordQ,orderBy
使用时就可以在filter
XXXData.objects.using('XXX').filter(keywordQ).exclude().order_by(orderBy)
网友评论