public
Description: Kikola is a collection of Django's custom context processors, form fields and widgets, middlewares, model fields, reusable apps and template tags.
Homepage:
Clone URL: git://github.com/playpauseandstop/kikola.git
commit  5e361cc67f359d0eac9ee963cac4a4bbdd747158
tree    57ee98f874f74f22fe633c06f96e3d6676632183
parent  3bd0b3b6229c8b31647f6ada1c1922c28151bb42
kikola / kikola / contrib / basicsearch / forms.py
100644 133 lines (103 sloc) 4.593 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
from django import forms
from django.conf import settings
from django.core.paginator import InvalidPage, Paginator
from django.db.models import Q, get_model
from django.template import Context, Template
from django.utils.translation import ugettext as _
 
from settings import *
 
 
__all__ = ('SearchForm', )
 
 
class SearchForm(forms.Form):
    query = forms.CharField(label=_('Search query'),
        min_length=SEARCH_QUERY_MIN_LENGTH, max_length=SEARCH_QUERY_MAX_LENGTH)
 
    def __init__(self, *args, **kwargs):
        if not 'request' in kwargs:
            raise TypeError, 'Please, supply `request` keyword argument first.'
 
        self.request = kwargs.pop('request')
        super(SearchForm, self).__init__(*args, **kwargs)
 
    def search(self):
        page = self.request.REQUEST.get('page', 1)
        per_page = self.request.REQUEST.get('per_page',
                                            SEARCH_RESULTS_PER_PAGE)
        query = self.cleaned_data['query']
        search_results = []
 
        result_dict = {'search_query': query}
 
        for model_name, options in SEARCH_MODELS.items():
            assert 'fields' in options, \
                   'Please, set up fields options for "%s".' % modelname
 
            app_label, model_name = model_name.split('.')
            model = get_model(app_label, model_name)
 
            description = options.get('description', False)
            fields = options['fields']
            fulltext = options.get('fulltext', False)
            link = options.get('link', False)
            priority = options.get('priority', 0)
            title = options.get('title', '{{ obj }}')
            trigger = options.get('trigger', None)
 
            if fulltext and settings.DATABASE_ENGINE == 'mysql':
                lookup = '%s__search'
            else:
                lookup = '%s__icontains'
 
            search_lookup = None
 
            for field in fields:
                if search_lookup is None:
                    search_lookup = Q(**{lookup % field: query})
                else:
                    search_lookup |= Q(**{lookup % field: query})
 
            objects = model.objects.filter(search_lookup)
 
            if not objects:
                continue
 
            description_template = \
                description and Template(description) or None
            title_template = title and Template(title) or None
 
            for obj in objects:
                if trigger is not None and not trigger(obj):
                    continue
 
                context = Context({'obj': obj})
 
                if description_template:
                    obj_description = description_template.render(context)
                else:
                    obj_description = description
 
                if link_template:
                    obj_link = link_template.render(context)
                else:
                    obj_link = obj.get_absolute_url()
 
                if title_template:
                    obj_title = title_template.render(context)
                else:
                    obj_title = title
 
                search_results.append({
                    'description': obj_description,
                    'link': obj_link,
                    'obj': obj,
                    'priority': priority,
                    'title': obj_title,
                })
 
        if not search_results:
            result_dict.update(
                {'search_error': SEARCH_NOT_FOUND_MESSAGE}
            )
            return result_dict
 
        search_results.sort(cmp=lambda x, y: cmp(y['priority'], x['priority']))
        paginator = Paginator(search_results, per_page)
 
        try:
            page_obj = paginator.page(page)
        except InvalidPage:
            result_dict.update(
                {'search_error': SEARCH_NOT_FOUND_MESSAGE}
            )
            return result_dict
 
        result_dict.update({
            'search_paginator': paginator,
            'search_results': page_obj.object_list,
 
            'search_count': paginator.count,
            'search_is_first_page': page_obj.number == 1,
            'search_is_last_page': page_obj.number == paginator.num_pages,
            'search_has_next_page': page_obj.has_next(),
            'search_has_previous_page': page_obj.has_previous(),
            'search_next_page': page_obj.number + 1,
            'search_page': page_obj,
            'search_pages': paginator.page_range,
            'search_pages_count': paginator.num_pages,
            'search_previous_page': page_obj.number - 1,
        })
        return result_dict