Simple search in Django

后端 未结 4 1101
北海茫月
北海茫月 2021-01-30 17:36

I have a really simple blog application and I want to add a really simple search feature to it.

There are 3 key fields to my model.

class BlogPost(models         


        
相关标签:
4条回答
  • 2021-01-30 18:05

    You would use the __search operator. It's documented in the Django QuerySet API Reference. There's also istartswith, which does a case-insensitive starts-with search.

    Here's a working example (adapted from my own Django site):

    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')
    

    Note that __search is only available in MySQL and requires direct manipulation of the database to add the full-text index. See the MySQL documentation for additional details.

    0 讨论(0)
  • 2021-01-30 18:07

    From the 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
    

    Clearly, it uses the database options to perform search. If nothing else, you should be able to reuse some of the code from it.

    So says the documentation too: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields

    The full text search, however, uses the MySQL index (only if you are using MySQL).

    0 讨论(0)
  • 2021-01-30 18:11

    If you want a really simple search you can use icontains lookup and 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))
    

    You should also note that Haystack doesn't have to be "hideously complicated". You can set up haystack with Whoosh backend in less then 15 minutes.

    Update 2016: In version 1.10 Django added a full text search support (PostgreSQL only). An answer to the original question using the new module might look something like this:

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

    The new full text search module contains a lot more features (for example sorting by relevancy), you can read about them in the documentation.

    0 讨论(0)
  • 2021-01-30 18:24

    If you want it to work just like the admin, you could try my mini-lib Django simple search. It's basically a port of the admin search functionality. Install it with pip:

    pip install django-simple-search
    

    and use it like:

    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))
    

    I also wrote a blog post about it: https://gregbrown.co/projects/django-simple-search

    0 讨论(0)
提交回复
热议问题