You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
5.3 KiB
145 lines
5.3 KiB
from django.template import loader, RequestContext |
|
from django.http import Http404, HttpResponse |
|
from django.core.xheaders import populate_xheaders |
|
from django.core.paginator import Paginator, 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 = Paginator(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
|
|
|