今天在修改之前做的一个搜索接口, 虽然使用了 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’, 变成了
<QueryDict: {u'xxx': [u'xxxx'], u'xx': [u'xxxxx'], u'xxxxxx': [u'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…