~ubuntu-branches/ubuntu/saucy/python-django/saucy-updates

« back to all changes in this revision

Viewing changes to django/views/generic/list.py

  • Committer: Package Import Robot
  • Author(s): Luke Faraone, Jakub Wilk, Luke Faraone
  • Date: 2013-05-09 15:10:47 UTC
  • mfrom: (1.1.21) (4.4.27 sid)
  • Revision ID: package-import@ubuntu.com-20130509151047-aqv8d71oj9wvcv8c
Tags: 1.5.1-2
[ Jakub Wilk ]
* Use canonical URIs for Vcs-* fields.

[ Luke Faraone ]
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from __future__ import unicode_literals
 
2
 
1
3
from django.core.paginator import Paginator, InvalidPage
2
4
from django.core.exceptions import ImproperlyConfigured
3
5
from django.http import Http404
4
 
from django.utils.encoding import smart_str
5
6
from django.utils.translation import ugettext as _
6
 
from django.views.generic.base import TemplateResponseMixin, View
7
 
 
8
 
 
9
 
class MultipleObjectMixin(object):
 
7
from django.views.generic.base import TemplateResponseMixin, ContextMixin, View
 
8
 
 
9
 
 
10
class MultipleObjectMixin(ContextMixin):
 
11
    """
 
12
    A mixin for views manipulating multiple objects.
 
13
    """
10
14
    allow_empty = True
11
15
    queryset = None
12
16
    model = None
13
17
    paginate_by = None
14
18
    context_object_name = None
15
19
    paginator_class = Paginator
 
20
    page_kwarg = 'page'
16
21
 
17
22
    def get_queryset(self):
18
23
        """
19
 
        Get the list of items for this view. This must be an interable, and may
 
24
        Get the list of items for this view. This must be an iterable, and may
20
25
        be a queryset (in which qs-specific behavior will be enabled).
21
26
        """
22
27
        if self.queryset is not None:
26
31
        elif self.model is not None:
27
32
            queryset = self.model._default_manager.all()
28
33
        else:
29
 
            raise ImproperlyConfigured(u"'%s' must define 'queryset' or 'model'"
 
34
            raise ImproperlyConfigured("'%s' must define 'queryset' or 'model'"
30
35
                                       % self.__class__.__name__)
31
36
        return queryset
32
37
 
35
40
        Paginate the queryset, if needed.
36
41
        """
37
42
        paginator = self.get_paginator(queryset, page_size, allow_empty_first_page=self.get_allow_empty())
38
 
        page = self.kwargs.get('page') or self.request.GET.get('page') or 1
 
43
        page_kwarg = self.page_kwarg
 
44
        page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1
39
45
        try:
40
46
            page_number = int(page)
41
47
        except ValueError:
42
48
            if page == 'last':
43
49
                page_number = paginator.num_pages
44
50
            else:
45
 
                raise Http404(_(u"Page is not 'last', nor can it be converted to an int."))
 
51
                raise Http404(_("Page is not 'last', nor can it be converted to an int."))
46
52
        try:
47
53
            page = paginator.page(page_number)
48
54
            return (paginator, page, page.object_list, page.has_other_pages())
49
 
        except InvalidPage:
50
 
            raise Http404(_(u'Invalid page (%(page_number)s)') % {
51
 
                                'page_number': page_number
 
55
        except InvalidPage as e:
 
56
            raise Http404(_('Invalid page (%(page_number)s): %(message)s') % {
 
57
                                'page_number': page_number,
 
58
                                'message': str(e)
52
59
            })
53
60
 
54
61
    def get_paginate_by(self, queryset):
77
84
        if self.context_object_name:
78
85
            return self.context_object_name
79
86
        elif hasattr(object_list, 'model'):
80
 
            return smart_str('%s_list' % object_list.model._meta.object_name.lower())
 
87
            return '%s_list' % object_list.model._meta.object_name.lower()
81
88
        else:
82
89
            return None
83
90
 
103
110
                'is_paginated': False,
104
111
                'object_list': queryset
105
112
            }
106
 
        context.update(kwargs)
107
113
        if context_object_name is not None:
108
114
            context[context_object_name] = queryset
109
 
        return context
 
115
        context.update(kwargs)
 
116
        return super(MultipleObjectMixin, self).get_context_data(**context)
110
117
 
111
118
 
112
119
class BaseListView(MultipleObjectMixin, View):
 
120
    """
 
121
    A base view for displaying a list of objects.
 
122
    """
113
123
    def get(self, request, *args, **kwargs):
114
124
        self.object_list = self.get_queryset()
115
125
        allow_empty = self.get_allow_empty()
116
 
        if not allow_empty and len(self.object_list) == 0:
117
 
            raise Http404(_(u"Empty list and '%(class_name)s.allow_empty' is False.")
118
 
                          % {'class_name': self.__class__.__name__})
 
126
 
 
127
        if not allow_empty:
 
128
            # When pagination is enabled and object_list is a queryset,
 
129
            # it's better to do a cheap query than to load the unpaginated
 
130
            # queryset in memory.
 
131
            if (self.get_paginate_by(self.object_list) is not None
 
132
                and hasattr(self.object_list, 'exists')):
 
133
                is_empty = not self.object_list.exists()
 
134
            else:
 
135
                is_empty = len(self.object_list) == 0
 
136
            if is_empty:
 
137
                raise Http404(_("Empty list and '%(class_name)s.allow_empty' is False.")
 
138
                        % {'class_name': self.__class__.__name__})
119
139
        context = self.get_context_data(object_list=self.object_list)
120
140
        return self.render_to_response(context)
121
141
 
122
142
 
123
143
class MultipleObjectTemplateResponseMixin(TemplateResponseMixin):
 
144
    """
 
145
    Mixin for responding with a template and list of objects.
 
146
    """
124
147
    template_name_suffix = '_list'
125
148
 
126
149
    def get_template_names(self):
127
150
        """
128
151
        Return a list of template names to be used for the request. Must return
129
 
        a list. May not be called if get_template is overridden.
 
152
        a list. May not be called if render_to_response is overridden.
130
153
        """
131
154
        try:
132
155
            names = super(MultipleObjectTemplateResponseMixin, self).get_template_names()