今天在修改之前做的一个搜索接口,虽然使用了haystack,但是由于需要修改请求参数和响应数据格式,所以大费周折调试了老一会儿,问题是这样的,大家如果有好的点子可以留言哦:
haystack默认的请求接口为
.../search?q=搜索关键字&models=xxxx.xxxx&models=xxxx.xxxx
我设计的接口
.../search?q=搜索关键字&f=搜索类型
我们的项目分为搜索全部及类型搜索,所以像默认的接口太暴露,所以我设计的短小干练了点,但是怎样去实现,看源码我实现了第一版:
class KaokaoSearchView(SearchView):
def __call__(self, request):
type = int(request.GET.get('f', 0))
models = {
0: 'xxx.xxxxx',
1: 'xx.xxxxx',
2: 'xxxxxx.xxxxxxxxx'
}
data = request.GET
_mutable = data._mutable
data._mutable = True
data['models'] = models.get(type, '')
data._mutable = _mutable
self.request = request
但是问题来了,多个model搜索怎样实现?我反正首先是进行照葫芦画瓢:
models = {
0: 'xxx.xxxxx',
1: 'xx.xxxxx',
2: 'xxxxxx.xxxxxxxxx',
9: 'xxx.xxxx&xx.xxxxx&xxxxxx.xxxxxxxxx'
}
结果是这样的:
而正确的应该是这样的:
原来models需要的是一个list,这好办
models = {
0: 'xxx.xxxxx',
1: 'xx.xxxxx',
2: 'xxxxxx.xxxxxxxxx',
9: ['xxx.xxxx', 'xx.xxxxx', 'xxxxxx.xxxxxxxxx']
}
出现了这种情况:
list嵌套?该怎么办呢?继续我的小聪明
data['models'] = models.get(type, '')
data['models'] = data['models'][0][1] + data['models'][0][1] + data['models'][0][2]
acc?什么鬼
原来此时的models还没有形成list嵌套,而是一个上面定义的list,也就说明我们的操作在了嵌套之前,怎么解决呢?那就看Django请求的完整过程吧,看看啥时候操作了这个东西...
结果
在django源码中:WSGIRequest中GET操作了这个query_string,源码是这样的:
class WSGIRequest(http.HttpRequest):
def __init__(self, environ):
...
@cached_property
def GET(self):
# The WSGI spec says 'QUERY_STRING' may be absent.
raw_query_string = get_bytes_from_wsgi(self.environ, 'QUERY_STRING', '')
return http.QueryDict(raw_query_string, encoding=self._encoding)
这个QueryDict将请求路径中的'xxx.xxxx&xx.xxxxx&xxxxxx.xxxxxxxxx',变成了
那这样就好办了
models = {
0: 'models=xxx.xxxxx',
1: 'models=xx.xxxxx',
2: 'models=xxxxxx.xxxxxxxxx',
9: 'models=xxx.xxxx&models=xx.xxxxx&models=xxxxxx.xxxxxxxxx'
}
data = request.GET
_mutable = data._mutable
data._mutable = True
data['models'] = http.QueryDict(models.get(type, ''))
data._mutable = _mutable
self.request = request
顺利解决!!!不知道大家看到在Django源码中的GET方法中有一个装饰器@cached_property,这是什么东西呢?
# 源码
class cached_property(object):
"""
Decorator that converts a method with a single self argument into a
property cached on the instance.
Optional ``name`` argument allows you to make cached properties of other
methods. (e.g. url = cached_property(get_absolute_url, name='url') )
"""
def __init__(self, func, name=None):
self.func = func
self.__doc__ = getattr(func, '__doc__')
self.name = name or func.__name__
def __get__(self, instance, cls=None):
if instance is None:
return self
res = instance.__dict__[self.name] = self.func(instance)
return res
这怎么起到cached的作用呢?大家认为的缓存应该都是用redis或这mongoDB这种数据库吧,如果你已经从事开发很长时间,请一定要去看这个东西:曾经我也写过一篇文章,今天拿出来,有需要的可以点开https://segmentfault.com/a/11...