2006-05-02 09:31:56 +08:00
|
|
|
from django.template import loader, RequestContext
|
|
|
|
from django.http import Http404, HttpResponse
|
2005-07-13 09:25:57 +08:00
|
|
|
from django.core.xheaders import populate_xheaders
|
2008-07-08 10:08:33 +08:00
|
|
|
from django.core.paginator import Paginator, InvalidPage
|
2006-05-02 09:31:56 +08:00
|
|
|
from django.core.exceptions import ObjectDoesNotExist
|
2005-07-13 09:25:57 +08:00
|
|
|
|
2006-06-04 06:06:48 +08:00
|
|
|
def object_list(request, queryset, paginate_by=None, page=None,
|
2007-12-02 23:43:35 +08:00
|
|
|
allow_empty=True, template_name=None, template_loader=loader,
|
2006-06-03 21:37:34 +08:00
|
|
|
extra_context=None, context_processors=None, template_object_name='object',
|
2006-05-31 23:08:06 +08:00
|
|
|
mimetype=None):
|
2005-07-13 09:25:57 +08:00
|
|
|
"""
|
|
|
|
Generic list of objects.
|
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
Templates: ``<app_label>/<model_name>_list.html``
|
2005-07-13 09:25:57 +08:00
|
|
|
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
|
2005-10-11 04:23:53 +08:00
|
|
|
hits
|
|
|
|
number of objects, total
|
2007-02-26 12:53:44 +08:00
|
|
|
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)
|
2007-09-14 09:01:02 +08:00
|
|
|
page_range:
|
|
|
|
A list of the page numbers (1-indexed).
|
2005-07-13 09:25:57 +08:00
|
|
|
"""
|
2006-06-03 21:37:34 +08:00
|
|
|
if extra_context is None: extra_context = {}
|
2006-05-02 09:31:56 +08:00
|
|
|
queryset = queryset._clone()
|
2005-07-13 09:25:57 +08:00
|
|
|
if paginate_by:
|
2008-07-08 13:29:23 +08:00
|
|
|
paginator = Paginator(queryset, paginate_by, allow_empty_first_page=allow_empty)
|
2006-06-04 06:06:48 +08:00
|
|
|
if not page:
|
|
|
|
page = request.GET.get('page', 1)
|
2005-07-13 09:25:57 +08:00
|
|
|
try:
|
2007-09-14 09:52:10 +08:00
|
|
|
page_number = int(page)
|
|
|
|
except ValueError:
|
|
|
|
if page == 'last':
|
2008-03-19 05:40:45 +08:00
|
|
|
page_number = paginator.num_pages
|
2007-09-14 09:52:10 +08:00
|
|
|
else:
|
2008-03-19 05:40:45 +08:00
|
|
|
# Page is not 'last', nor can it be converted to an int.
|
2007-09-14 09:52:10 +08:00
|
|
|
raise Http404
|
|
|
|
try:
|
2008-03-19 05:40:45 +08:00
|
|
|
page_obj = paginator.page(page_number)
|
2007-09-14 09:52:10 +08:00
|
|
|
except InvalidPage:
|
2008-03-19 05:40:45 +08:00
|
|
|
raise Http404
|
2006-05-02 09:31:56 +08:00
|
|
|
c = RequestContext(request, {
|
2008-03-19 05:40:45 +08:00
|
|
|
'%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(),
|
2008-03-23 13:45:59 +08:00
|
|
|
'first_on_page': page_obj.start_index(),
|
|
|
|
'last_on_page': page_obj.end_index(),
|
2008-03-19 05:40:45 +08:00
|
|
|
'pages': paginator.num_pages,
|
|
|
|
'hits': paginator.count,
|
|
|
|
'page_range': paginator.page_range,
|
2005-12-24 12:39:59 +08:00
|
|
|
}, context_processors)
|
2005-07-13 09:25:57 +08:00
|
|
|
else:
|
2006-05-02 09:31:56 +08:00
|
|
|
c = RequestContext(request, {
|
|
|
|
'%s_list' % template_object_name: queryset,
|
2008-03-19 05:40:45 +08:00
|
|
|
'paginator': None,
|
|
|
|
'page_obj': None,
|
|
|
|
'is_paginated': False,
|
2005-12-24 12:39:59 +08:00
|
|
|
}, context_processors)
|
2006-05-02 09:31:56 +08:00
|
|
|
if not allow_empty and len(queryset) == 0:
|
2005-09-03 06:54:12 +08:00
|
|
|
raise Http404
|
2005-07-26 05:53:00 +08:00
|
|
|
for key, value in extra_context.items():
|
|
|
|
if callable(value):
|
|
|
|
c[key] = value()
|
2005-08-09 03:45:57 +08:00
|
|
|
else:
|
2005-07-26 05:53:00 +08:00
|
|
|
c[key] = value
|
2005-07-13 09:25:57 +08:00
|
|
|
if not template_name:
|
2006-05-24 03:34:43 +08:00
|
|
|
model = queryset.model
|
2006-05-02 09:31:56 +08:00
|
|
|
template_name = "%s/%s_list.html" % (model._meta.app_label, model._meta.object_name.lower())
|
2005-07-13 09:25:57 +08:00
|
|
|
t = template_loader.get_template(template_name)
|
2007-06-22 15:15:04 +08:00
|
|
|
return HttpResponse(t.render(c), mimetype=mimetype)
|
2005-07-13 09:25:57 +08:00
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
def object_detail(request, queryset, object_id=None, slug=None,
|
2007-08-12 20:59:41 +08:00
|
|
|
slug_field='slug', template_name=None, template_name_field=None,
|
2006-06-03 21:37:34 +08:00
|
|
|
template_loader=loader, extra_context=None,
|
2006-05-31 23:08:06 +08:00
|
|
|
context_processors=None, template_object_name='object',
|
|
|
|
mimetype=None):
|
2005-07-13 09:25:57 +08:00
|
|
|
"""
|
2006-11-28 07:38:49 +08:00
|
|
|
Generic detail of an object.
|
2005-07-13 09:25:57 +08:00
|
|
|
|
2006-05-02 09:31:56 +08:00
|
|
|
Templates: ``<app_label>/<model_name>_detail.html``
|
2005-07-13 09:25:57 +08:00
|
|
|
Context:
|
|
|
|
object
|
2005-08-09 03:45:57 +08:00
|
|
|
the object
|
2005-07-13 09:25:57 +08:00
|
|
|
"""
|
2006-06-03 21:37:34 +08:00
|
|
|
if extra_context is None: extra_context = {}
|
2006-05-02 09:31:56 +08:00
|
|
|
model = queryset.model
|
2005-07-13 09:25:57 +08:00
|
|
|
if object_id:
|
2006-05-02 09:31:56 +08:00
|
|
|
queryset = queryset.filter(pk=object_id)
|
2005-07-13 09:25:57 +08:00
|
|
|
elif slug and slug_field:
|
2006-05-02 09:31:56 +08:00
|
|
|
queryset = queryset.filter(**{slug_field: slug})
|
2005-07-13 09:25:57 +08:00
|
|
|
else:
|
2010-01-11 02:36:20 +08:00
|
|
|
raise AttributeError("Generic detail view must be called with either an object_id or a slug/slug_field.")
|
2005-07-13 09:25:57 +08:00
|
|
|
try:
|
2006-05-02 09:31:56 +08:00
|
|
|
obj = queryset.get()
|
2005-07-13 09:25:57 +08:00
|
|
|
except ObjectDoesNotExist:
|
2010-01-11 02:36:20 +08:00
|
|
|
raise Http404("No %s found matching the query" % (model._meta.verbose_name))
|
2005-07-13 09:25:57 +08:00
|
|
|
if not template_name:
|
2006-05-02 09:31:56 +08:00
|
|
|
template_name = "%s/%s_detail.html" % (model._meta.app_label, model._meta.object_name.lower())
|
2005-07-13 09:25:57 +08:00
|
|
|
if template_name_field:
|
2006-05-02 09:31:56 +08:00
|
|
|
template_name_list = [getattr(obj, template_name_field), template_name]
|
2005-07-13 09:25:57 +08:00
|
|
|
t = template_loader.select_template(template_name_list)
|
|
|
|
else:
|
|
|
|
t = template_loader.get_template(template_name)
|
2006-05-02 09:31:56 +08:00
|
|
|
c = RequestContext(request, {
|
|
|
|
template_object_name: obj,
|
2005-12-24 12:39:59 +08:00
|
|
|
}, context_processors)
|
2005-07-26 05:53:00 +08:00
|
|
|
for key, value in extra_context.items():
|
|
|
|
if callable(value):
|
|
|
|
c[key] = value()
|
2005-08-09 03:45:57 +08:00
|
|
|
else:
|
2005-07-26 05:53:00 +08:00
|
|
|
c[key] = value
|
2007-06-22 15:15:04 +08:00
|
|
|
response = HttpResponse(t.render(c), mimetype=mimetype)
|
2006-05-02 09:31:56 +08:00
|
|
|
populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name))
|
2005-07-13 09:25:57 +08:00
|
|
|
return response
|