Ticket #2197: generic-search.diff
File generic-search.diff, 12.8 KB (added by , 18 years ago) |
---|
-
django/db/models/manager.py
99 99 def values(self, *args, **kwargs): 100 100 return self.get_query_set().values(*args, **kwargs) 101 101 102 def search(self, *args, **kwargs): 103 return self.get_query_set().search(*args, **kwargs) 104 102 105 class ManagerDescriptor(object): 103 106 # This class ensures managers aren't accessible via model instances. 104 107 # For example, Poll.objects works, but poll_obj.objects raises AttributeError. -
django/db/models/options.py
13 13 14 14 DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering', 15 15 'unique_together', 'permissions', 'get_latest_by', 16 'order_with_respect_to', 'app_label' )16 'order_with_respect_to', 'app_label', 'search_fields') 17 17 18 18 class Options(object): 19 19 def __init__(self, meta): … … 22 22 self.verbose_name_plural = None 23 23 self.db_table = '' 24 24 self.ordering = [] 25 self.search_fields = [] 25 26 self.unique_together = [] 26 27 self.permissions = [] 27 28 self.object_name, self.app_label = None, None … … 197 198 198 199 class AdminOptions(object): 199 200 def __init__(self, fields=None, js=None, list_display=None, list_filter=None, 200 date_hierarchy=None, save_as=False, ordering=None, search_fields=None,201 date_hierarchy=None, save_as=False, ordering=None, 201 202 save_on_top=False, list_select_related=False, manager=None, list_per_page=100): 202 203 self.fields = fields 203 204 self.js = js or [] … … 205 206 self.list_filter = list_filter or [] 206 207 self.date_hierarchy = date_hierarchy 207 208 self.save_as, self.ordering = save_as, ordering 208 self.search_fields = search_fields or []209 209 self.save_on_top = save_on_top 210 210 self.list_select_related = list_select_related 211 211 self.list_per_page = list_per_page -
django/db/models/query.py
233 233 "Cannot change a query once a slice has been taken." 234 234 return self._clone(_limit=1, _order_by=('-'+latest_by,)).get() 235 235 236 def search(self, query, field_names=None): 237 """ 238 Return all objects who has any the words in the given query 239 in any of it's fields given in the model's 'search_fields' 240 option or in the optional argument field_names. 241 """ 242 search_fields = field_names or self.model._meta.search_fields 243 assert bool(search_fields), "search_fields() requires either a field_names parameter or 'search_fields' in the model" 244 assert self._limit is None and self._offset is None, \ 245 "Cannot change a query once a slice has been taken." 246 247 or_queries = [] 248 for bit in query.split(): 249 for field_name in search_fields: 250 or_queries.append(Q(**{'%s__icontains' % field_name: bit})) 251 252 if or_queries: 253 return self._clone().filter(reduce(operator.or_, or_queries)) 254 else: 255 return self 256 236 257 def in_bulk(self, id_list): 237 258 """ 238 259 Returns a dictionary mapping each of the given IDs to the object with -
django/core/management.py
930 930 except models.FieldDoesNotExist: 931 931 e.add(opts, '"ordering" refers to "%s", a field that doesn\'t exist.' % field_name) 932 932 933 # Check search_fields attribute. 934 if opts.search_fields: 935 for field_name in opts.search_fields: 936 try: 937 opts.get_field(field_name, many_to_many=False) 938 except models.FieldDoesNotExist: 939 e.add(opts, '"search_fields" refers to "%s", a field that doesn\'t exist.' % field_name) 940 933 941 # Check core=True, if needed. 934 942 for related in opts.get_followed_related_objects(): 935 943 try: -
django/views/generic/list_detail.py
7 7 def object_list(request, queryset, paginate_by=None, page=None, 8 8 allow_empty=False, template_name=None, template_loader=loader, 9 9 extra_context=None, context_processors=None, template_object_name='object', 10 mimetype=None ):10 mimetype=None, allow_search=True): 11 11 """ 12 12 Generic list of objects. 13 13 … … 33 33 number of pages, total 34 34 hits 35 35 number of objects, total 36 query 37 the search query string 36 38 """ 37 39 if extra_context is None: extra_context = {} 38 40 queryset = queryset._clone() 41 42 query = request.GET.get('query', '') 43 if searchable and queryset.model._meta.search_fields and query: 44 queryset = queryset.search(query) 45 39 46 if paginate_by: 40 47 paginator = ObjectPaginator(queryset, paginate_by) 41 48 if not page: … … 59 66 'previous': page - 1, 60 67 'pages': paginator.pages, 61 68 'hits' : paginator.hits, 69 'query': query, 62 70 }, context_processors) 63 71 else: 64 72 c = RequestContext(request, { 65 73 '%s_list' % template_object_name: queryset, 66 'is_paginated': False 74 'is_paginated': False, 75 'query': query, 67 76 }, context_processors) 68 77 if not allow_empty and len(queryset) == 0: 69 78 raise Http404 -
django/contrib/auth/models.py
29 29 verbose_name = _('group') 30 30 verbose_name_plural = _('groups') 31 31 ordering = ('name',) 32 class Admin:33 32 search_fields = ('name',) 34 33 34 class Admin: 35 pass 36 35 37 def __str__(self): 36 38 return self.name 37 39 … … 70 72 verbose_name = _('user') 71 73 verbose_name_plural = _('users') 72 74 ordering = ('username',) 75 search_fields = ('username', 'first_name', 'last_name', 'email') 73 76 class Admin: 74 77 fields = ( 75 78 (None, {'fields': ('username', 'password')}), … … 80 83 ) 81 84 list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff') 82 85 list_filter = ('is_staff', 'is_superuser') 83 search_fields = ('username', 'first_name', 'last_name', 'email')84 86 85 87 def __str__(self): 86 88 return self.username -
django/contrib/redirects/models.py
15 15 db_table = 'django_redirect' 16 16 unique_together=(('site', 'old_path'),) 17 17 ordering = ('old_path',) 18 search_fields = ('old_path', 'new_path') 18 19 19 20 class Admin: 20 21 list_filter = ('site',) 21 search_fields = ('old_path', 'new_path')22 22 23 23 def __str__(self): 24 24 return "%s ---> %s" % (self.old_path, self.new_path) -
django/contrib/comments/models.py
90 90 verbose_name = _('comment') 91 91 verbose_name_plural = _('comments') 92 92 ordering = ('-submit_date',) 93 search_fields = ('comment', 'user__username') 93 94 class Admin: 94 95 fields = ( 95 96 (None, {'fields': ('content_type', 'object_id', 'site')}), … … 100 101 list_display = ('user', 'submit_date', 'content_type', 'get_content_object') 101 102 list_filter = ('submit_date',) 102 103 date_hierarchy = 'submit_date' 103 search_fields = ('comment', 'user__username')104 104 105 105 def __repr__(self): 106 106 return "%s: %s..." % (self.user.username, self.comment[:100]) … … 176 176 verbose_name = _('free comment') 177 177 verbose_name_plural = _('free comments') 178 178 ordering = ('-submit_date',) 179 search_fields = ('comment', 'person_name') 179 180 class Admin: 180 181 fields = ( 181 182 (None, {'fields': ('content_type', 'object_id', 'site')}), … … 185 186 list_display = ('person_name', 'submit_date', 'content_type', 'get_content_object') 186 187 list_filter = ('submit_date',) 187 188 date_hierarchy = 'submit_date' 188 search_fields = ('comment', 'person_name')189 189 190 190 def __repr__(self): 191 191 return "%s: %s..." % (self.person_name, self.comment[:100]) -
django/contrib/flatpages/models.py
18 18 verbose_name = _('flat page') 19 19 verbose_name_plural = _('flat pages') 20 20 ordering = ('url',) 21 search_fields = ('url', 'title') 21 22 class Admin: 22 23 fields = ( 23 24 (None, {'fields': ('url', 'title', 'content', 'sites')}), 24 25 ('Advanced options', {'classes': 'collapse', 'fields': ('enable_comments', 'registration_required', 'template_name')}), 25 26 ) 26 27 list_filter = ('sites',) 27 search_fields = ('url', 'title')28 28 29 29 def __str__(self): 30 30 return "%s -- %s" % (self.url, self.title) -
django/contrib/sites/models.py
15 15 verbose_name = _('site') 16 16 verbose_name_plural = _('sites') 17 17 ordering = ('domain',) 18 search_fields = ('domain', 'name') 18 19 class Admin: 19 20 list_display = ('domain', 'name') 20 search_fields = ('domain', 'name')21 21 22 22 def __str__(self): 23 23 return self.domain -
django/contrib/admin/views/main.py
710 710 qs = qs.order_by((self.order_type == 'desc' and '-' or '') + lookup_order_field) 711 711 712 712 # Apply keyword searches. 713 if self.lookup_opts.admin.search_fields and self.query: 714 for bit in self.query.split(): 715 or_queries = [models.Q(**{'%s__icontains' % field_name: bit}) for field_name in self.lookup_opts.admin.search_fields] 716 other_qs = QuerySet(self.model) 717 other_qs = other_qs.filter(reduce(operator.or_, or_queries)) 718 qs = qs & other_qs 713 if self.opts.search_fields and self.query: 714 qs = qs.search(self.query) 719 715 720 716 if self.opts.one_to_one_field: 721 717 qs = qs.complex_filter(self.opts.one_to_one_field.rel.limit_choices_to) -
django/contrib/admin/templates/admin/search_form.html
1 1 {% load adminmedia %} 2 2 {% load i18n %} 3 {% if cl. lookup_opts.admin.search_fields %}3 {% if cl.opts.search_fields %} 4 4 <div id="toolbar"><form id="changelist-search" action="" method="get"> 5 5 <div><!-- DIV needed for valid HTML --> 6 6 <label for="searchbar"><img src="{% admin_media_prefix %}img/admin/icon_searchbox.png" alt="Search" /></label> -
docs/generic_views.txt
673 673 * ``mimetype``: The MIME type to use for the resulting document. Defaults 674 674 to the value of the ``DEFAULT_MIME_TYPE`` setting. 675 675 676 * ``allow_search``: A boolean specifying whether searching is allowed 677 for theese objects. If this is ``False``, objects will not be 678 searchable. By default, this is ``True``. 679 676 680 **Template name:** 677 681 678 682 If ``template_name`` isn't specified, this view will use the template … … 713 717 * ``hits``: The total number of objects across *all* pages, not just this 714 718 page. 715 719 720 * ``query``: The search query string. if searching is disabled, 721 this is an empty string. 722 716 723 Notes on pagination 717 724 ~~~~~~~~~~~~~~~~~~~ 718 725