| 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 |
| |
| import warnings |
| warnings.warn( |
| 'Function-based generic views have been deprecated; use class-based views instead.', |
| PendingDeprecationWarning |
| ) |
| |
| |
| 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, |
| 'is_paginated': page_obj.has_other_pages(), |
| |
| # Legacy template context stuff. New templates should use page_obj |
| # to access this instead. |
| '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 |