Django search method I have done this small piece of code used to search for a given word across several fields of a Django model. 

Goal was to have first entries equals to the word, then entries starting by the world and finally just entries containing it.

I would like to have feedback on it :

# -*- coding: utf-8 -*-
"""Module created to search a specific term in several fields of a model"""
from itertools import chain
import operator

from django.db.models import Q

__author__ = 'trnsnt'


def search_for_term(model, term, fields, number=10):
    """
    Generic method used to search term on list of fields.
    Return first fields equals to term, then fields starting by the term, and at the end fields containing term
    :param model: Django model class
    :param term: Searched term
    :param fields: Fields to look for
    :param number: Number of wanted response
    :return: List of objects
    """
    searcher = ['iexact', 'istartswith', 'icontains']
    objects = []
    for search in searcher:
        curr_filter = reduce(operator.or_, [Q(('%s__%s' % (field, search), term)) for field in fields])
        # Need to search for number to handle duplicate objects
        objects = uniquify(objects, model.objects.filter(curr_filter)[:number])[:number]
        if len(objects) == number:
            return objects
    return objects


def uniquify(*queryests):
    """Take several queryset and return list of unique object
    :param queryests: QuerySets we want to uniquify
    """
    seen = set()
    return [x for x in chain(*queryests) if not (x in seen or seen.add(x))]
Nice doc-strings. I enjoyed seeing your code. I have just a few comments.

Use built-in functions instead of rolling your own

My guess would be that you could improve the efficiency of uniquify and also make the code more expressive/easier to digest by returning the list version of a union of all the sets in querysets rather than rolling your own solution. Something like this should work (I didn't run it):

full_set = set().union(*query_sets)
return list(full_set)


Another option relying on built-in functionality would be to return a set out of the chaining you already do:

return set(chain(*queryests))


In fact coming back to this, I think you should return a set. It doesn't seem that you later need a list since you're just checking membership. I believe checking set membership is much faster than checking list membership.

Logic

I apologize if I am misunderstanding your logic, but it seems in search_for_term that you want to return early when you find at least number number of results. However, right now you only return early if you find exactly that number of results. Wouldn't you want to modify your early return as:

    if len(objects) &gt;= number:
        return objects


If not it might be helpful to add a comment explaining the logic of returning when you have exactly a certain number of results.

Little nits

Notice you've got a typo in your parameter name queryests. I would recommend using snake_case as in my example above.

Since you're only using operator.or_, consider importing just that function.