app/django/views/generic/list_detail.py
changeset 54 03e267d67478
child 323 ff1a9aa48cfd
equal deleted inserted replaced
53:57b4279d8c4e 54:03e267d67478
       
     1 from django.template import loader, RequestContext
       
     2 from django.http import Http404, HttpResponse
       
     3 from django.core.xheaders import populate_xheaders
       
     4 from django.core.paginator import QuerySetPaginator, InvalidPage
       
     5 from django.core.exceptions import ObjectDoesNotExist
       
     6 
       
     7 def object_list(request, queryset, paginate_by=None, page=None,
       
     8         allow_empty=True, template_name=None, template_loader=loader,
       
     9         extra_context=None, context_processors=None, template_object_name='object',
       
    10         mimetype=None):
       
    11     """
       
    12     Generic list of objects.
       
    13 
       
    14     Templates: ``<app_label>/<model_name>_list.html``
       
    15     Context:
       
    16         object_list
       
    17             list of objects
       
    18         is_paginated
       
    19             are the results paginated?
       
    20         results_per_page
       
    21             number of objects per page (if paginated)
       
    22         has_next
       
    23             is there a next page?
       
    24         has_previous
       
    25             is there a prev page?
       
    26         page
       
    27             the current page
       
    28         next
       
    29             the next page
       
    30         previous
       
    31             the previous page
       
    32         pages
       
    33             number of pages, total
       
    34         hits
       
    35             number of objects, total
       
    36         last_on_page
       
    37             the result number of the last of object in the
       
    38             object_list (1-indexed)
       
    39         first_on_page
       
    40             the result number of the first object in the
       
    41             object_list (1-indexed)
       
    42         page_range:
       
    43             A list of the page numbers (1-indexed).
       
    44     """
       
    45     if extra_context is None: extra_context = {}
       
    46     queryset = queryset._clone()
       
    47     if paginate_by:
       
    48         paginator = QuerySetPaginator(queryset, paginate_by, allow_empty_first_page=allow_empty)
       
    49         if not page:
       
    50             page = request.GET.get('page', 1)
       
    51         try:
       
    52             page_number = int(page)
       
    53         except ValueError:
       
    54             if page == 'last':
       
    55                 page_number = paginator.num_pages
       
    56             else:
       
    57                 # Page is not 'last', nor can it be converted to an int.
       
    58                 raise Http404
       
    59         try:
       
    60             page_obj = paginator.page(page_number)
       
    61         except InvalidPage:
       
    62             raise Http404
       
    63         c = RequestContext(request, {
       
    64             '%s_list' % template_object_name: page_obj.object_list,
       
    65             'paginator': paginator,
       
    66             'page_obj': page_obj,
       
    67 
       
    68             # Legacy template context stuff. New templates should use page_obj
       
    69             # to access this instead.
       
    70             'is_paginated': page_obj.has_other_pages(),
       
    71             'results_per_page': paginator.per_page,
       
    72             'has_next': page_obj.has_next(),
       
    73             'has_previous': page_obj.has_previous(),
       
    74             'page': page_obj.number,
       
    75             'next': page_obj.next_page_number(),
       
    76             'previous': page_obj.previous_page_number(),
       
    77             'first_on_page': page_obj.start_index(),
       
    78             'last_on_page': page_obj.end_index(),
       
    79             'pages': paginator.num_pages,
       
    80             'hits': paginator.count,
       
    81             'page_range': paginator.page_range,
       
    82         }, context_processors)
       
    83     else:
       
    84         c = RequestContext(request, {
       
    85             '%s_list' % template_object_name: queryset,
       
    86             'paginator': None,
       
    87             'page_obj': None,
       
    88             'is_paginated': False,
       
    89         }, context_processors)
       
    90         if not allow_empty and len(queryset) == 0:
       
    91             raise Http404
       
    92     for key, value in extra_context.items():
       
    93         if callable(value):
       
    94             c[key] = value()
       
    95         else:
       
    96             c[key] = value
       
    97     if not template_name:
       
    98         model = queryset.model
       
    99         template_name = "%s/%s_list.html" % (model._meta.app_label, model._meta.object_name.lower())
       
   100     t = template_loader.get_template(template_name)
       
   101     return HttpResponse(t.render(c), mimetype=mimetype)
       
   102 
       
   103 def object_detail(request, queryset, object_id=None, slug=None,
       
   104         slug_field='slug', template_name=None, template_name_field=None,
       
   105         template_loader=loader, extra_context=None,
       
   106         context_processors=None, template_object_name='object',
       
   107         mimetype=None):
       
   108     """
       
   109     Generic detail of an object.
       
   110 
       
   111     Templates: ``<app_label>/<model_name>_detail.html``
       
   112     Context:
       
   113         object
       
   114             the object
       
   115     """
       
   116     if extra_context is None: extra_context = {}
       
   117     model = queryset.model
       
   118     if object_id:
       
   119         queryset = queryset.filter(pk=object_id)
       
   120     elif slug and slug_field:
       
   121         queryset = queryset.filter(**{slug_field: slug})
       
   122     else:
       
   123         raise AttributeError, "Generic detail view must be called with either an object_id or a slug/slug_field."
       
   124     try:
       
   125         obj = queryset.get()
       
   126     except ObjectDoesNotExist:
       
   127         raise Http404, "No %s found matching the query" % (model._meta.verbose_name)
       
   128     if not template_name:
       
   129         template_name = "%s/%s_detail.html" % (model._meta.app_label, model._meta.object_name.lower())
       
   130     if template_name_field:
       
   131         template_name_list = [getattr(obj, template_name_field), template_name]
       
   132         t = template_loader.select_template(template_name_list)
       
   133     else:
       
   134         t = template_loader.get_template(template_name)
       
   135     c = RequestContext(request, {
       
   136         template_object_name: obj,
       
   137     }, context_processors)
       
   138     for key, value in extra_context.items():
       
   139         if callable(value):
       
   140             c[key] = value()
       
   141         else:
       
   142             c[key] = value
       
   143     response = HttpResponse(t.render(c), mimetype=mimetype)
       
   144     populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
       
   145     return response