今天在修改之前做的一個搜索接口,雖然使用了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...