Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (10.6 kB)

1
# Copyright 2011-2012 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.exceptions import PermissionDenied
37
from django.core.xheaders import populate_xheaders
38
from django.http import HttpResponse
39
from django.shortcuts import redirect
40
from django.template import RequestContext, loader as template_loader
41
from django.utils.translation import ugettext as _
42
from django.views.generic.create_update import apply_extra_context, \
43
    get_model_and_form_class, lookup_object
44

    
45
from synnefo.lib.ordereddict import OrderedDict
46

    
47
from snf_django.lib.db.transaction import commit_on_success_strict
48

    
49
from astakos.im import presentation
50
from astakos.im.util import model_to_dict
51
from astakos.im.models import Resource
52

    
53
def render_response(template, tab=None, status=200, context_instance=None, **kwargs):
54
    """
55
    Calls ``django.template.loader.render_to_string`` with an additional ``tab``
56
    keyword argument and returns an ``django.http.HttpResponse`` with the
57
    specified ``status``.
58
    """
59
    if tab is None:
60
        tab = template.partition('_')[0].partition('.html')[0]
61
    kwargs.setdefault('tab', tab)
62
    html = template_loader.render_to_string(
63
        template, kwargs, context_instance=context_instance)
64
    response = HttpResponse(html, status=status)
65
    return response
66

    
67
@commit_on_success_strict()
68
def _create_object(request, model=None, template_name=None,
69
        template_loader=template_loader, extra_context=None, post_save_redirect=None,
70
        login_required=False, context_processors=None, form_class=None,
71
        msg=None):
72
    """
73
    Based of django.views.generic.create_update.create_object which displays a
74
    summary page before creating the object.
75
    """
76
    response = None
77

    
78
    if extra_context is None: extra_context = {}
79
    if login_required and not request.user.is_authenticated():
80
        return redirect_to_login(request.path)
81
    try:
82

    
83
        model, form_class = get_model_and_form_class(model, form_class)
84
        extra_context['edit'] = 0
85
        if request.method == 'POST':
86
            form = form_class(request.POST, request.FILES)
87
            if form.is_valid():
88
                verify = request.GET.get('verify')
89
                edit = request.GET.get('edit')
90
                if verify == '1':
91
                    extra_context['show_form'] = False
92
                    extra_context['form_data'] = form.cleaned_data
93
                elif edit == '1':
94
                    extra_context['show_form'] = True
95
                else:
96
                    new_object = form.save()
97
                    if not msg:
98
                        msg = _("The %(verbose_name)s was created successfully.")
99
                    msg = msg % model._meta.__dict__
100
                    messages.success(request, msg, fail_silently=True)
101
                    response = redirect(post_save_redirect, new_object)
102
        else:
103
            form = form_class()
104
    except (IOError, PermissionDenied), e:
105
        messages.error(request, e)
106
        return None
107
    else:
108
        if response == None:
109
            # Create the template, context, response
110
            if not template_name:
111
                template_name = "%s/%s_form.html" %\
112
                     (model._meta.app_label, model._meta.object_name.lower())
113
            t = template_loader.get_template(template_name)
114
            c = RequestContext(request, {
115
                'form': form
116
            }, context_processors)
117
            apply_extra_context(extra_context, c)
118
            response = HttpResponse(t.render(c))
119
        return response
120

    
121
@commit_on_success_strict()
122
def _update_object(request, model=None, object_id=None, slug=None,
123
        slug_field='slug', template_name=None, template_loader=template_loader,
124
        extra_context=None, post_save_redirect=None, login_required=False,
125
        context_processors=None, template_object_name='object',
126
        form_class=None, msg=None):
127
    """
128
    Based of django.views.generic.create_update.update_object which displays a
129
    summary page before updating the object.
130
    """
131
    response = None
132

    
133
    if extra_context is None: extra_context = {}
134
    if login_required and not request.user.is_authenticated():
135
        return redirect_to_login(request.path)
136

    
137
    try:
138
        model, form_class = get_model_and_form_class(model, form_class)
139
        obj = lookup_object(model, object_id, slug, slug_field)
140

    
141
        if request.method == 'POST':
142
            form = form_class(request.POST, request.FILES, instance=obj)
143
            if form.is_valid():
144
                verify = request.GET.get('verify')
145
                edit = request.GET.get('edit')
146
                if verify == '1':
147
                    extra_context['show_form'] = False
148
                    extra_context['form_data'] = form.cleaned_data
149
                elif edit == '1':
150
                    extra_context['show_form'] = True
151
                else:
152
                    obj = form.save()
153
                    if not msg:
154
                        msg = _("The %(verbose_name)s was created successfully.")
155
                    msg = msg % model._meta.__dict__
156
                    messages.success(request, msg, fail_silently=True)
157
                    response = redirect(post_save_redirect, obj)
158
        else:
159
            form = form_class(instance=obj)
160
    except (IOError, PermissionDenied), e:
161
        messages.error(request, e)
162
        return None
163
    else:
164
        if response == None:
165
            if not template_name:
166
                template_name = "%s/%s_form.html" %\
167
                    (model._meta.app_label, model._meta.object_name.lower())
168
            t = template_loader.get_template(template_name)
169
            c = RequestContext(request, {
170
                'form': form,
171
                template_object_name: obj,
172
            }, context_processors)
173
            apply_extra_context(extra_context, c)
174
            response = HttpResponse(t.render(c))
175
            populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.attname))
176
        return response
177

    
178
def _resources_catalog(for_project=False, for_usage=False):
179
    """
180
    `resource_catalog` contains a list of tuples. Each tuple contains the group
181
    key the resource is assigned to and resources list of dicts that contain
182
    resource information.
183
    `resource_groups` contains information about the groups
184
    """
185
    # presentation data
186
    resources_meta = presentation.RESOURCES
187
    resource_groups = resources_meta.get('groups', {})
188
    resource_catalog = ()
189
    resource_keys = []
190

    
191
    # resources in database
192
    resource_details = map(lambda obj: model_to_dict(obj, exclude=[]),
193
                           Resource.objects.all())
194
    # initialize resource_catalog to contain all group/resource information
195
    for r in resource_details:
196
        if not r.get('group') in resource_groups:
197
            resource_groups[r.get('group')] = {'icon': 'unknown'}
198

    
199
    resource_keys = [r.get('str_repr') for r in resource_details]
200
    resource_catalog = [[g, filter(lambda r: r.get('group', '') == g,
201
                                   resource_details)] for g in resource_groups]
202

    
203
    # order groups, also include unknown groups
204
    groups_order = resources_meta.get('groups_order')
205
    for g in resource_groups.keys():
206
        if not g in groups_order:
207
            groups_order.append(g)
208

    
209
    # order resources, also include unknown resources
210
    resources_order = resources_meta.get('resources_order')
211
    for r in resource_keys:
212
        if not r in resources_order:
213
            resources_order.append(r)
214

    
215
    # sort catalog groups
216
    resource_catalog = sorted(resource_catalog,
217
                              key=lambda g: groups_order.index(g[0]))
218

    
219
    # sort groups
220
    def groupindex(g):
221
        return groups_order.index(g[0])
222
    resource_groups_list = sorted([(k, v) for k, v in resource_groups.items()],
223
                                  key=groupindex)
224
    resource_groups = OrderedDict(resource_groups_list)
225

    
226
    # sort resources
227
    def resourceindex(r):
228
        return resources_order.index(r['str_repr'])
229

    
230
    for index, group in enumerate(resource_catalog):
231
        resource_catalog[index][1] = sorted(resource_catalog[index][1],
232
                                            key=resourceindex)
233
        if len(resource_catalog[index][1]) == 0:
234
            resource_catalog.pop(index)
235
            for gindex, g in enumerate(resource_groups):
236
                if g[0] == group[0]:
237
                    resource_groups.pop(gindex)
238

    
239
    # filter out resources which user cannot request in a project application
240
    exclude = resources_meta.get('exclude_from_usage', [])
241
    for group_index, group_resources in enumerate(list(resource_catalog)):
242
        group, resources = group_resources
243
        for index, resource in list(enumerate(resources)):
244
            if for_project and not resource.get('allow_in_projects'):
245
                resources.remove(resource)
246
            if resource.get('str_repr') in exclude and for_usage:
247
                resources.remove(resource)
248

    
249
    # cleanup empty groups
250
    for group_index, group_resources in enumerate(list(resource_catalog)):
251
        group, resources = group_resources
252
        if len(resources) == 0:
253
            resource_catalog.pop(group_index)
254
            resource_groups.pop(group)
255

    
256

    
257
    return resource_catalog, resource_groups