代码之家  ›  专栏  ›  技术社区  ›  Oli

Django中的简单搜索

  •  23
  • Oli  · 技术社区  · 16 年前

    我有一个非常简单的博客应用程序,我想添加一个非常简单的搜索功能。

    我的模型有3个关键字段。

    class BlogPost(models.Model):
        title = models.CharField(max_length=100) # the title
        intro = models.TextField(blank=True, null=True) # an extract
        content = models.TextField(blank=True, null=True) # full post
    

    我不需要谷歌。我不想搜索评论(不管怎样,这些评论都放在disqs上)。我只想要一个日期排序,关键字过滤的帖子集。

    所有这些。我不想在低使用率的特性上消耗更多的资源(在我移植到Django之前,我曾经有一个搜索框,一个月可能有4次搜索)。

    我在这里花时间问的原因(而不仅仅是写一个凌乱的小脚本)是 这已经存在于管理员中

    有什么方法可以控制管理员提供的搜索并将其拉入我面向用户的应用程序?

    4 回复  |  直到 8 年前
        1
  •  50
  •   Ludwik Trammer    7 年前

    如果你想要一个非常简单的搜索,你可以使用 icontains 查找和 Q object :

    from django.db.models import Q
    results = BlogPost.objects.filter(Q(title__icontains=your_search_query) | Q(intro__icontains=your_search_query) | Q(content__icontains=your_search_query))
    

    您还应该注意到,Haystack不必“极其复杂”。你可以在不到15分钟的时间内用Whoosh后端设置haystack。

    2016年更新: a full text search support

    from django.contrib.postgres.search import SearchVector
    
    results = BlogPost.objects.annotate(
        search=SearchVector('title', 'intro', 'content'),
    ).filter(search=your_search_query)
    

    新的全文搜索模块包含了更多的功能(例如按相关性排序),您可以 read about them in the documentation .

        2
  •  6
  •   D Malan    5 年前

    来自Django source

    # Apply keyword searches.
    def construct_search(field_name):
        if field_name.startswith('^'):
            return "%s__istartswith" % field_name[1:]
        elif field_name.startswith('='):
            return "%s__iexact" % field_name[1:]
        elif field_name.startswith('@'):
            return "%s__search" % field_name[1:]
        else:
            return "%s__icontains" % field_name
    
    if self.search_fields and self.query:
        for bit in self.query.split():
            or_queries = [models.Q(**{construct_search(str(field_name)): bit}) for field_name in self.search_fields]
            qs = qs.filter(reduce(operator.or_, or_queries))
        for field_name in self.search_fields:
            if '__' in field_name:
                qs = qs.distinct()
                break
    

    显然,它使用数据库选项来执行搜索。如果没有其他问题,您应该能够重用其中的一些代码。

    文件也这么说: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields

        3
  •  4
  •   Frederik    13 年前

    您将使用搜索运算符。文件上有记载 Django QuerySet API Reference . 还有 istartswith ,不区分大小写,从搜索开始。

    def search(request):
        try:
            q = request.GET['q']
            posts = BlogPost.objects.filter(title__search=q) | \
                    BlogPost.objects.filter(intro__search=q) | \
                    BlogPost.objects.filter(content__search=q)
            return render_to_response('search/results.html', {'posts':posts, 'q':q})
        except KeyError:
            return render_to_response('search/results.html')
    

    注意,\uu search只在MySQL中可用,需要直接操作数据库来添加全文索引。看到了吗 MySQL documentation

        4
  •  1
  •   Greg    9 年前

    如果你想让它像管理员一样工作,你可以试试我的迷你lib Django simple search

    pip install django-simple-search
    

    使用方法如下:

    from simple_search import search_filter
    from .models import BlogPost
    
    search_fields = ['^title', 'intro', 'content']
    query = 'search term here'
    posts = BlogPost.objects.filter(search_filter(search_fields, query))
    

    https://gregbrown.co/projects/django-simple-search