app/django/views/generic/list_detail.py
changeset 54 03e267d67478
child 323 ff1a9aa48cfd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/django/views/generic/list_detail.py	Fri Jul 18 18:22:23 2008 +0000
@@ -0,0 +1,145 @@
+from django.template import loader, RequestContext
+from django.http import Http404, HttpResponse
+from django.core.xheaders import populate_xheaders
+from django.core.paginator import QuerySetPaginator, InvalidPage
+from django.core.exceptions import ObjectDoesNotExist
+
+def object_list(request, queryset, paginate_by=None, page=None,
+        allow_empty=True, template_name=None, template_loader=loader,
+        extra_context=None, context_processors=None, template_object_name='object',
+        mimetype=None):
+    """
+    Generic list of objects.
+
+    Templates: ``<app_label>/<model_name>_list.html``
+    Context:
+        object_list
+            list of objects
+        is_paginated
+            are the results paginated?
+        results_per_page
+            number of objects per page (if paginated)
+        has_next
+            is there a next page?
+        has_previous
+            is there a prev page?
+        page
+            the current page
+        next
+            the next page
+        previous
+            the previous page
+        pages
+            number of pages, total
+        hits
+            number of objects, total
+        last_on_page
+            the result number of the last of object in the
+            object_list (1-indexed)
+        first_on_page
+            the result number of the first object in the
+            object_list (1-indexed)
+        page_range:
+            A list of the page numbers (1-indexed).
+    """
+    if extra_context is None: extra_context = {}
+    queryset = queryset._clone()
+    if paginate_by:
+        paginator = QuerySetPaginator(queryset, paginate_by, allow_empty_first_page=allow_empty)
+        if not page:
+            page = request.GET.get('page', 1)
+        try:
+            page_number = int(page)
+        except ValueError:
+            if page == 'last':
+                page_number = paginator.num_pages
+            else:
+                # Page is not 'last', nor can it be converted to an int.
+                raise Http404
+        try:
+            page_obj = paginator.page(page_number)
+        except InvalidPage:
+            raise Http404
+        c = RequestContext(request, {
+            '%s_list' % template_object_name: page_obj.object_list,
+            'paginator': paginator,
+            'page_obj': page_obj,
+
+            # Legacy template context stuff. New templates should use page_obj
+            # to access this instead.
+            'is_paginated': page_obj.has_other_pages(),
+            'results_per_page': paginator.per_page,
+            'has_next': page_obj.has_next(),
+            'has_previous': page_obj.has_previous(),
+            'page': page_obj.number,
+            'next': page_obj.next_page_number(),
+            'previous': page_obj.previous_page_number(),
+            'first_on_page': page_obj.start_index(),
+            'last_on_page': page_obj.end_index(),
+            'pages': paginator.num_pages,
+            'hits': paginator.count,
+            'page_range': paginator.page_range,
+        }, context_processors)
+    else:
+        c = RequestContext(request, {
+            '%s_list' % template_object_name: queryset,
+            'paginator': None,
+            'page_obj': None,
+            'is_paginated': False,
+        }, context_processors)
+        if not allow_empty and len(queryset) == 0:
+            raise Http404
+    for key, value in extra_context.items():
+        if callable(value):
+            c[key] = value()
+        else:
+            c[key] = value
+    if not template_name:
+        model = queryset.model
+        template_name = "%s/%s_list.html" % (model._meta.app_label, model._meta.object_name.lower())
+    t = template_loader.get_template(template_name)
+    return HttpResponse(t.render(c), mimetype=mimetype)
+
+def object_detail(request, queryset, object_id=None, slug=None,
+        slug_field='slug', template_name=None, template_name_field=None,
+        template_loader=loader, extra_context=None,
+        context_processors=None, template_object_name='object',
+        mimetype=None):
+    """
+    Generic detail of an object.
+
+    Templates: ``<app_label>/<model_name>_detail.html``
+    Context:
+        object
+            the object
+    """
+    if extra_context is None: extra_context = {}
+    model = queryset.model
+    if object_id:
+        queryset = queryset.filter(pk=object_id)
+    elif slug and slug_field:
+        queryset = queryset.filter(**{slug_field: slug})
+    else:
+        raise AttributeError, "Generic detail view must be called with either an object_id or a slug/slug_field."
+    try:
+        obj = queryset.get()
+    except ObjectDoesNotExist:
+        raise Http404, "No %s found matching the query" % (model._meta.verbose_name)
+    if not template_name:
+        template_name = "%s/%s_detail.html" % (model._meta.app_label, model._meta.object_name.lower())
+    if template_name_field:
+        template_name_list = [getattr(obj, template_name_field), template_name]
+        t = template_loader.select_template(template_name_list)
+    else:
+        t = template_loader.get_template(template_name)
+    c = RequestContext(request, {
+        template_object_name: obj,
+    }, context_processors)
+    for key, value in extra_context.items():
+        if callable(value):
+            c[key] = value()
+        else:
+            c[key] = value
+    response = HttpResponse(t.render(c), mimetype=mimetype)
+    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
+    return response