2013-08-19 158 views
0

我想实现在Django搜索功能,过滤基于字符串的记录列表,同样存在于django admin list filtering实现字符串搜索功能

但一个在这里我们不打算进行过滤基于查询字符串的结果from the database从搜索表单了,相反,我们需要filter from the list我已经

views.py

def filter_contacts(request): 
    contacts = ['None <[email protected]>', 'None <[email protected]>', 
       'None <[email protected]>', 'None <[email protected]>' ...... up to more than 1000] 
    if request.GET: 
     if request.GET.has_key('q'): 
      contacts = **filter the contacts from the above list that contains query string "q" and create a new list** 
     else: 
      contacts = contacts 
    return render_to_response('social_feeds/gmail_contacts.html', {'contacts':contacts}) 

search_form像

<form class="form-search" action="{% url 'contacts' %}" method="get"> 
     <div class="input-append"> 
     <input type="text" class="span2 search-query" name="q" value="" id="searchbar"> 
     <button type="submit" class="btn btn-primary" value="Search">Search</button> 
     </div> 
</form> 

我们当然可以通过looping从列表过滤query string和搜索每个字符串,并在列表中,如果它有创建一个新的列表中的每个字符串,

但是因为/假设我们有超过1000个字符串(电子邮件大概如上),那么这个过程应该是very/ultimately快,所以寻找functionality/process/method,基于query paramerter非常快地过滤列表,如假设

如果我们搜索与steve形式,都包含steve应该被过滤到一个新的列表,这就是我所寻找的

任何一个可以请让我知道如何实现搜索功能非常快strings/emails

+0

您正在寻找的是'autocomplete'。那里有很多文档。还有一个名为'django-autocomplete'的第三方应用程序可能会让你感兴趣 – karthikr

+0

@karthikr:但是当我想要结果仅在点击搜索按钮之后被过滤时呢? –

回答

0

最快的方法是将电子邮件置于数据库中,然后使用查询来获取它们。事情是这样的:

models.py

class Contact(models.model): 
    email = models.EmailField() 

,然后在views.py:

if request.GET.has_key('q'): 
    query = request.GET['q'] 
    contacts = Contact.objects.all().filter(email__contains=query) 

如果做不到这一点,你要使用Python的方式。除了简单循环外,可能有更快的方法,但是再循环,循环速度并不像你想象的那么慢。我参加了一个60K的电子邮件列表(this one!),以及环绕在它所谓的“慢法”,例如:

​​

和时间,这表明,花了大约0.008秒的时间完成。

只是为了展示如何快速的“简单”的方法可能是,我计时达到相同的结果不同的方法:

timing = {} 
res = [] 
import time 

# normal iteration 
start = time.time() 
for l in lines: 
    if 'steve' in l: 
     res.append(l) 
end = time.time() 
timing['iteration'] = end-start 
length = len(res) 


res = [] 
# list comprehension 
start = time.time() 
[res.append(l) for l in lines if 'steve' in l] 
end = time.time() 
timing['list comprehension'] = end-start 
assert(len(res) == length) 

# 
def search(s): 
    res =[] 
    if 'steve' in s: 
     res.append(s) 
    return res 

# built in 'filter' method 
start = time.time() 
res = filter(search, lines) 
end = time.time() 
timing['filter'] = end-start 
assert(len(res) == length) 

#using itertools 
import itertools 
start = time.time() 
res = itertools.ifilter(search, lines) 
end = time.time() 
timing['ifilter'] = end-start 

for key, value in timing.iteritems(): 
    print key, value, 'seconds' 

线是上述60K电子邮件列表名单,结果,其中如下:

iteration     0.00799989700317 seconds 
list comprehension   0.00699996948242 seconds 
filter      0.0130000114441 seconds 
ifilter     0.0 seconds 

正如你所看到的,最快的方法是使用列表理解。这是为了计算'steve'是否在电子邮件中,但如果你做了一些更复杂的事情,就像'史蒂夫'在电子邮件或'史密斯'在电子邮件比结果改变一点点:

iteration     0.0139999389648 seconds 
list comprehension   0.010999917984 seconds 
filter      0.0169999599457 seconds 
ifilter     0.0 seconds 

不过,列表理解是胜利者。您可能想知道为什么ifilter需要0次,但很简单 - ifilter创建了一个生成器。动态加载结果可以证明您的需求是有效的。

无论如何,正如您可以清楚地看到的,所有这些版本之间的差异都是以毫秒为单位。我无法想象你需要比这更快的任何东西,但是你应该测试和计算不同的方法,并且如果你发现你仍然需要更多的东西,那么去pypi并寻找一个允许快速过滤的包。

+0

其实我会从'gmail'得到那些电子邮件列表(类似从gmail导入联系人),所以我没有办法将它们全部保存到数据库中,我将立即收到电子邮件,并且需要过滤当用户在搜索表单中输入一些单词时基于查询字符串的列表 –

+0

我扩展了我的答案。希望这可以帮助 – yuvi