예제 #1
0
def perform_search(keywords, normalized=False, queryset=None):
    """Perform the search"""
    
    results = [] # The list of results starts empty
    actions_list = []

    if not normalized:
        keywords = normalize_query(keywords)
    
    # All keywords 'OR' which aren't followed and preceded by something MUST be
    # ignored.
    #
    # test OR world # OK!
    # test OR # Ignored
    # OR test # Ignored
    for i, keyword in enumerate(keywords):
        if keyword == 'OR' and not(i > 0 and i < len(keywords)-1):
            keywords.pop(i)

    # For each keyword
    for i, keyword in enumerate(keywords):
        if keyword == 'OR':
            # This keyword is an 'OR' statement and isn't the first nor the last
            # keyword
            kwds = [w(keywords[i-1]), w(keywords[i+1])]
            regexp = re.compile('|'.join(kwds), re.IGNORECASE)
            actions_list.append(('required', regexp))
        elif not keyword == 'OR':
            test = MINUS_CAPTURE_REGEXP.search(keyword)
            if test:
                # This keyword is an exclusion keyword
                regexp = re.compile(w(test.group(1)), re.IGNORECASE)
                actions_list.append(('not', regexp))
            else:
                leave = False
                if i+1 < len(keywords):
                    if keywords[i+1] == 'OR':
                        leave = True
                if not leave and i > 0:
                    if keywords[i-1] == 'OR':
                        leave = True
                if not leave:
                    regexp = re.compile(w(keyword), re.IGNORECASE)
                    actions_list.append(('required', regexp))

    models = [] # we'll store actual model references here, along with the queryset to use

    if queryset:
        models.append((queryset.model, queryset))
        name = queryset.model._meta.verbose_name.capitalize()

    else:
        model_names = settings.LIGHTSEARCH_MODELS

        for full_name in model_names:
            # The model link is <appname>.<model>
            link = full_name[1]
            # It's verbose name
            name = full_name[0]
            # Retrieve the model
            object = get_model(*link.split('.'))
            if object is None:
                raise Exception, "This model (%s) doesn't exist!" % full_name
            models.append((object, object.objects.all()))

    for object, objects in models:                
        # Create a new instance of the model
        instance = object()
        # Get the fields
        fields = instance.Lightsearch.fields

        # Make the list of results concerning this model empty
        objects_results = []
    
        # Loop on objects in the database
        for obj in objects:
            validated_actions = [ False for i in xrange(len(actions_list)) ]
            
            for i, action in enumerate(actions_list):
                if action[0] == 'not':
                    validated_actions[i] = True
            
            add_it = True
            for field in fields: # For each field allowed
                content = getattr(obj, field)

                for i, action in enumerate(actions_list):
                    result = action[1].findall(content)
                    
                    if result and action[0] == 'required':
                        # This action is needed and it returned something
                        validated_actions[i] = True
                        
                    elif result and action[0] == 'not':
                        # This action mustn't be validated and it returned
                        # something
                        validated_actions[i] = False
            
            for valids in validated_actions:
                if not valids:
                    add_it = False
                    break
            
            if add_it: # Finally, if the object validate all the conditions,
                objects_results.append(obj) # add it
            
        results.append((name, objects_results))
    container = ResultsContainer(results)
    return container
예제 #2
0
def search(form):
    """Normalize the query from a form then perform the search"""
    keywords = normalize_query(form.cleaned_data['query'])
    return perform_search(keywords, normalized=True)