在django中实现字符串搜索功能

时间:2013-08-19 14:35:24

标签: django forms list search

我正在尝试在django中实现一个搜索功能,它根据字符串过滤记录列表,与django admin list filtering

中的字符串相同

但是,我们不会根据从搜索表单中获取的查询字符串来过滤结果from the database,而是我们需要filter from the list我已经

views.py

def filter_contacts(request):
    contacts = ['None <steve.one@gmail.com>', 'None <ronold@gmail.com>', 
               'None <jacksparrow@gmail.com>', 'None <dude@gmail.com>' ...... 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>

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

但是,自从/假设我们有超过1000个字符串(可能是上面的电子邮件),该过程应该very/ultimately快,所以寻找基于{functionality/process/method非常快速过滤列表的query paramerter {1}}喜欢假设

如果我们使用steve搜索表单,则应将包含strings/emails的所有steve过滤到新列表,这就是我要找的内容

任何人都可以告诉我如何快速实现搜索功能吗?

1 个答案:

答案 0 :(得分: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)

如果失败了,你想要使用pythonic方式。可能有更快的方法而不是简单的循环,但是再次,循环并不像你想象的那么慢。我拿了一个60k的电子邮件列表(this one!),并在所谓的“慢速方法”中循环使用它,如下所示:

f = open('maillist.txt', 'rb')
lines = f.readlines()
res = []
for l in lines:
    if 'steve' in l:
        res.append(l)

时间表明它需要大约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',但是如果你做了一些更复杂的事情,比如电子邮件中的'steve'或电子邮件中的'smith'比结果稍有变化:

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

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

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