Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / views / util.py @ a3e3917f

History | View | Annotate | Download (10.6 kB)

1
# Copyright 2011, 2012, 2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from django.contrib import messages
35
from django.contrib.auth.views import redirect_to_login
36
from django.core.xheaders import populate_xheaders
37
from django.http import HttpResponse
38
from django.shortcuts import redirect
39
from django.template import RequestContext, loader as template_loader
40
from django.utils.translation import ugettext as _
41
from django.views.generic.create_update import apply_extra_context, \
42
    get_model_and_form_class, lookup_object
43

    
44
from synnefo.lib.ordereddict import OrderedDict
45

    
46
from astakos.im import presentation
47
from astakos.im.util import model_to_dict
48
from astakos.im.models import Resource
49
import astakos.im.messages as astakos_messages
50
import logging
51

    
52
logger = logging.getLogger(__name__)
53

    
54

    
55
class ExceptionHandler(object):
56
    def __init__(self, request):
57
        self.request = request
58

    
59
    def __enter__(self):
60
        pass
61

    
62
    def __exit__(self, exc_type, value, traceback):
63
        if value is not None:  # exception
64
            logger.exception(value)
65
            m = _(astakos_messages.GENERIC_ERROR)
66
            messages.error(self.request, m)
67
            return True  # suppress exception
68

    
69

    
70
def render_response(template, tab=None, status=200, context_instance=None,
71
                    **kwargs):
72
    """
73
    Calls ``django.template.loader.render_to_string`` with an additional
74
    ``tab`` keyword argument and returns an ``django.http.HttpResponse``
75
    with the specified ``status``.
76
    """
77
    if tab is None:
78
        tab = template.partition('_')[0].partition('.html')[0]
79
    kwargs.setdefault('tab', tab)
80
    html = template_loader.render_to_string(
81
        template, kwargs, context_instance=context_instance)
82
    response = HttpResponse(html, status=status)
83
    return response
84

    
85

    
86
def _create_object(request, model=None, template_name=None,
87
                   template_loader=template_loader, extra_context=None,
88
                   post_save_redirect=None, login_required=False,
89
                   context_processors=None, form_class=None, msg=None,
90
                   summary_template_name=None):
91
    """
92
    Based of django.views.generic.create_update.create_object which displays a
93
    summary page before creating the object.
94
    """
95

    
96
    if extra_context is None:
97
        extra_context = {}
98
    if login_required and not request.user.is_authenticated():
99
        return redirect_to_login(request.path)
100

    
101
    model, form_class = get_model_and_form_class(model, form_class)
102
    extra_context['edit'] = 0
103
    if request.method == 'POST':
104
        form = form_class(request.POST, request.FILES)
105
        if form.is_valid():
106
            verify = request.GET.get('verify')
107
            edit = request.GET.get('edit')
108
            if verify == '1':
109
                extra_context['show_form'] = False
110
                extra_context['form_data'] = form.cleaned_data
111
                template_name = summary_template_name
112
            elif edit == '1':
113
                extra_context['show_form'] = True
114
            else:
115
                new_object = form.save()
116
                if not msg:
117
                    msg = _(
118
                        "The %(verbose_name)s was created successfully.")
119
                msg = msg % model._meta.__dict__
120
                messages.success(request, msg, fail_silently=True)
121
                return redirect(post_save_redirect, new_object)
122
    else:
123
        form = form_class()
124

    
125
    # Create the template, context, response
126
    if not template_name:
127
        template_name = "%s/%s_form.html" % \
128
            (model._meta.app_label, model._meta.object_name.lower())
129
    t = template_loader.get_template(template_name)
130
    c = RequestContext(request, {
131
        'form': form
132
    }, context_processors)
133
    apply_extra_context(extra_context, c)
134
    return HttpResponse(t.render(c))
135

    
136

    
137
def _update_object(request, model=None, object_id=None, slug=None,
138
                   slug_field='slug', template_name=None,
139
                   template_loader=template_loader, extra_context=None,
140
                   post_save_redirect=None, login_required=False,
141
                   context_processors=None, template_object_name='object',
142
                   form_class=None, msg=None, summary_template_name=None):
143
    """
144
    Based of django.views.generic.create_update.update_object which displays a
145
    summary page before updating the object.
146
    """
147

    
148
    if extra_context is None:
149
        extra_context = {}
150
    if login_required and not request.user.is_authenticated():
151
        return redirect_to_login(request.path)
152

    
153
    model, form_class = get_model_and_form_class(model, form_class)
154
    obj = lookup_object(model, object_id, slug, slug_field)
155

    
156
    if request.method == 'POST':
157
        form = form_class(request.POST, request.FILES, instance=obj)
158
        if form.is_valid():
159
            verify = request.GET.get('verify')
160
            edit = request.GET.get('edit')
161
            if verify == '1':
162
                extra_context['show_form'] = False
163
                extra_context['form_data'] = form.cleaned_data
164
                template_name = summary_template_name
165
            elif edit == '1':
166
                extra_context['show_form'] = True
167
            else:
168
                obj = form.save()
169
                if not msg:
170
                    msg = _(
171
                        "The %(verbose_name)s was created successfully.")
172
                msg = msg % model._meta.__dict__
173
                messages.success(request, msg, fail_silently=True)
174
                return redirect(post_save_redirect, obj)
175
    else:
176
        form = form_class(instance=obj)
177

    
178
    if not template_name:
179
        template_name = "%s/%s_form.html" % \
180
            (model._meta.app_label, model._meta.object_name.lower())
181
    t = template_loader.get_template(template_name)
182
    c = RequestContext(request, {
183
        'form': form,
184
        template_object_name: obj,
185
    }, context_processors)
186
    apply_extra_context(extra_context, c)
187
    response = HttpResponse(t.render(c))
188
    populate_xheaders(request, response, model,
189
                      getattr(obj, obj._meta.pk.attname))
190
    return response
191

    
192

    
193
def _resources_catalog(for_project=False, for_usage=False):
194
    """
195
    `resource_catalog` contains a list of tuples. Each tuple contains the group
196
    key the resource is assigned to and resources list of dicts that contain
197
    resource information.
198
    `resource_groups` contains information about the groups
199
    """
200
    # presentation data
201
    resources_meta = presentation.RESOURCES
202
    resource_groups = resources_meta.get('groups', {})
203
    resource_catalog = ()
204
    resource_keys = []
205

    
206
    # resources in database
207
    resource_details = map(lambda obj: model_to_dict(obj, exclude=[]),
208
                           Resource.objects.all())
209
    # initialize resource_catalog to contain all group/resource information
210
    for r in resource_details:
211
        if not r.get('group') in resource_groups:
212
            resource_groups[r.get('group')] = {'icon': 'unknown'}
213

    
214
    resource_keys = [r.get('str_repr') for r in resource_details]
215
    resource_catalog = [[g, filter(lambda r: r.get('group', '') == g,
216
                                   resource_details)] for g in resource_groups]
217

    
218
    # order groups, also include unknown groups
219
    groups_order = resources_meta.get('groups_order')
220
    for g in resource_groups.keys():
221
        if not g in groups_order:
222
            groups_order.append(g)
223

    
224
    # order resources, also include unknown resources
225
    resources_order = resources_meta.get('resources_order')
226
    for r in resource_keys:
227
        if not r in resources_order:
228
            resources_order.append(r)
229

    
230
    # sort catalog groups
231
    resource_catalog = sorted(resource_catalog,
232
                              key=lambda g: groups_order.index(g[0]))
233

    
234
    # sort groups
235
    def groupindex(g):
236
        return groups_order.index(g[0])
237
    resource_groups_list = sorted([(k, v) for k, v in resource_groups.items()],
238
                                  key=groupindex)
239
    resource_groups = OrderedDict(resource_groups_list)
240

    
241
    # sort resources
242
    def resourceindex(r):
243
        return resources_order.index(r['str_repr'])
244

    
245
    for index, group in enumerate(resource_catalog):
246
        resource_catalog[index][1] = sorted(resource_catalog[index][1],
247
                                            key=resourceindex)
248
        if len(resource_catalog[index][1]) == 0:
249
            resource_catalog.pop(index)
250
            for gindex, g in enumerate(resource_groups):
251
                if g[0] == group[0]:
252
                    resource_groups.pop(gindex)
253

    
254
    # filter out resources which user cannot request in a project application
255
    exclude = resources_meta.get('exclude_from_usage', [])
256
    for group_index, group_resources in enumerate(list(resource_catalog)):
257
        group, resources = group_resources
258
        for index, resource in list(enumerate(resources)):
259
            if for_project and not resource.get('allow_in_projects'):
260
                resources.remove(resource)
261
            if resource.get('str_repr') in exclude and for_usage:
262
                resources.remove(resource)
263

    
264
    # cleanup empty groups
265
    for group_index, group_resources in enumerate(list(resource_catalog)):
266
        group, resources = group_resources
267
        if len(resources) == 0:
268
            resource_catalog.pop(group_index)
269
            resource_groups.pop(group)
270

    
271
    return resource_catalog, resource_groups