Move default template for tables out of template into table base class
[ganeti_webmgr.git] / ganeti_web / views / generic.py
blobe51b5d187c4523c3d9eb56953a30633812586c81
1 # Copyright (c) 2012 Oregon State University
3 # Generic class-based view mixins and helpers.
5 from django.conf import settings
6 from django.contrib.auth.decorators import login_required
7 from django.core.exceptions import ImproperlyConfigured
8 from django.utils.decorators import method_decorator
9 from django.utils.http import urlencode
10 from django.utils.translation import ugettext as _
12 # Standard translation messages. We use these everywhere.
14 NO_PRIVS = _('You do not have sufficient privileges')
17 class LoginRequiredMixin(object):
18 """
19 Helper mixin which applies @login_required to all methods on a view.
21 Meant to massively simplify the four-line prelude common to many of our
22 views.
23 """
25 @method_decorator(login_required)
26 def dispatch(self, *args, **kwargs):
27 return super(LoginRequiredMixin, self).dispatch(*args, **kwargs)
30 class PaginationMixin(object):
31 """
32 Helper which automatically applies uniform pagination options to any
33 paginated ListView.
34 """
36 paginate_by = settings.ITEMS_PER_PAGE # list view
37 table_pagination = {"per_page": settings.ITEMS_PER_PAGE} # table view
39 def get_paginate_by(self, queryset):
40 """
41 Return the number of items to paginate by.
43 I like the wording on the other docstring: "An integer specifying how
44 many objects should be displayed per page."
45 """
47 return self.request.GET.get("count", self.paginate_by)
50 class SortingMixin(object):
51 """
52 A mixin which provides sorting for a ListView
53 """
55 default_sort_params = None
57 def get_context_data(self, **kwargs):
58 context = super(SortingMixin, self).get_context_data(**kwargs)
59 sort_by, order = self.get_sort_params()
60 params = {'sort_by': sort_by, 'order': order}
61 # Store the sort querystring for the current page for easy reuse in
62 # templates
63 sort_query = urlencode(params)
64 params.update({'sort_query': sort_query})
65 context.update(params)
66 return context
68 def get_default_sort_params(self):
69 if self.default_sort_params is None:
70 raise ImproperlyConfigured(
71 "'SortMixin' requires the 'default_sort_params' "
72 "attribute to be set."
74 return self.default_sort_params
76 def get_sort_params(self):
77 default_sort_by, default_order = self.get_default_sort_params()
78 sort_by = self.request.GET.get('sort_by', default_sort_by)
79 order = self.request.GET.get('order', default_order)
80 return (sort_by, order)
82 def get_queryset(self):
83 return self.sort_queryset(
84 super(SortingMixin, self).get_queryset(),
85 *self.get_sort_params())
87 def sort_queryset(self, qs, sort_by, order):
88 """
89 This method is how to specify sorting in your view. By default it
90 implements a very basic sorting which will use 'sort_by' as the field
91 to sort, and 'order' as the sorting order.
93 This is the main function to override and modify for sorting. Any sort
94 params passed in the url will be passed into this method for use.
95 """
96 qs = qs.order_by(sort_by)
97 if order == 'desc':
98 qs = qs.reverse()
99 return qs
102 class GWMBaseView(object):
104 A base view which will filter querysets by cluster, primary node, or
105 secondary node. It will also saves these to context data.
107 This base already includes our standard mixins and if a more custom view is
108 necessary, the methods can be overloaded.
110 def get_kwargs(self):
112 Get common URL kwargs and assign as object variables.
114 This is a useful utility method that should be used if you don't want
115 to call super() on you queryset method at the beginning.
117 self.cluster_slug = self.kwargs.get("cluster_slug", None)
118 self.pnode = self.kwargs.get("primary_node", None)
119 self.snode = self.kwargs.get("secondary_node", None)
121 def get_queryset(self):
122 self.get_kwargs() # Make sure that we have our values.
123 qs = super(GWMBaseView, self).get_queryset()
124 # Filter by cluster if applicable
125 if self.cluster_slug:
126 qs = qs.filter(cluster__slug=self.cluster_slug)
128 # filter the vms by primary node if applicable
129 if self.pnode:
130 qs = qs.filter(primary_node=self.pnode)
132 # filter the vms by the secondary node if applicable
133 if self.snode:
134 qs = qs.filter(secondary_node=self.snode)
136 return qs
138 def get_context_data(self, **kwargs):
139 self.get_kwargs()
140 context = super(GWMBaseView, self).get_context_data(**kwargs)
141 context['cluster_slug'] = self.cluster_slug
143 return context
145 def can_create(self, cluster):
147 Given an instance of a cluster or all clusters returns
148 whether or not the logged in user is able to create a VM.
150 user = self.request.user
151 return (user.is_superuser or user.has_any_perms(cluster,
152 ["admin", "create_vm"]))