Issues (70)

django-data/image/common/views.py (2 issues)

1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Mon Oct 29 15:33:34 2018
5
6
@author: Paolo Cozzi <[email protected]>
7
"""
8
9
import logging
10
11
from functools import wraps
12
13
from django.contrib.auth.mixins import LoginRequiredMixin
14
from django.contrib import messages
15
from django.http import HttpResponseBadRequest
16
from django.utils import timezone
17
from django.utils.decorators import method_decorator
18
from django.shortcuts import redirect
19
from django.urls import reverse
20
from django.views.generic.base import TemplateView
21
22
from .constants import NEED_REVISION
23
24
# Get an instance of a logger
25
logger = logging.getLogger(__name__)
26
27
28
# a mixin to isolate user data
29
class OwnerMixin(LoginRequiredMixin):
30
    def get_queryset(self):
31
        """
32
        Filter base queryset relying on django authenticated sessions::
33
34
            from common.views import OwnerMixin
35
            from django.views.generic import DetailView
36
37
            class MyDetailView(OwnerMixin, DetailView):
38
                def get_queryset(self):
39
                    # call OwnerMixin and DetailView super methods
40
                    qs = super(MyDetailView, self).get_queryset()
41
42
                    # add custom filter to queryset
43
44
                    # remeber to return the updated queryset to the caller
45
                    return qs
46
        """
47
48
        qs = super(OwnerMixin, self).get_queryset()
49
        logger.debug("Checking '%s' ownership for user '%s'" % (
50
            self.request.path, self.request.user))
51
        return qs.filter(owner=self.request.user)
52
53
54
class DetailMaterialMixin(OwnerMixin):
55
    """A common DetailMixin for Material classes (Sample/Animal)"""
56
57
    def get_context_data(self, **kwargs):
58
        data = super().get_context_data(**kwargs)
59
60
        # get a validationresult obj
61
        if self.object.validationresult:
62
            validation = self.object.validationresult
63
64
            logger.debug(
65
                "Found validationresult: %s->%s" % (
66
                    validation, validation.messages))
67
68
            # I could have more messages in validation message. They could
69
            # be werning or errors, validation.status (overall status)
70
            # has no meaning here
71
            for message in validation.messages:
72
                if "Info:" in message:
73
                    messages.info(
74
                        request=self.request,
75
                        message=message,
76
                        extra_tags="alert alert-dismissible alert-info")
77
78
                elif "Warning:" in message:
79
                    messages.warning(
80
                        request=self.request,
81
                        message=message,
82
                        extra_tags="alert alert-dismissible alert-warning")
83
84
                # the other validation messages are threated like errors
85
                else:
86
                    messages.error(
87
                        request=self.request,
88
                        message=message,
89
                        extra_tags="alert alert-dismissible alert-danger")
90
91
            # cicle for a message in validation.messages
92
93
        # condition: I have validation result
94
        return data
95
96
97
class UpdateMaterialMixin(OwnerMixin):
98
    """A common UpdateMixin for Material classes (Sample/Animal)"""
99
100
    # override this attribute with a real validation class
101
    validationresult_class = None
102
103 View Code Duplication
    def dispatch(self, request, *args, **kwargs):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
104
        handler = super(UpdateMaterialMixin, self).dispatch(
105
                request, *args, **kwargs)
106
107
        # here I've done get_queryset. Check for submission status
108
        if hasattr(self, "object") and not self.object.can_edit():
109
            message = "Cannot edit %s: submission status is: %s" % (
110
                    self.object, self.object.submission.get_status_display())
111
112
            logger.warning(message)
113
            messages.warning(
114
                request=self.request,
115
                message=message,
116
                extra_tags="alert alert-dismissible alert-warning")
117
118
            return redirect(self.object.get_absolute_url())
119
120
        return handler
121
122
    # add the request to the kwargs
123
    # https://chriskief.com/2012/12/18/django-modelform-formview-and-the-request-object/
124
    def get_form_kwargs(self):
125
        kwargs = super(UpdateMaterialMixin, self).get_form_kwargs()
126
        kwargs['request'] = self.request
127
        return kwargs
128
129
    # override UpdateView.get_form() method. Initialize a form object
130
    # and pass submission into it. Self object is the animal object I
131
    # want to update
132
    def get_form(self):
133
        return self.form_class(
134
            self.object, **self.get_form_kwargs())
135
136
    # override form valid istance
137
    def form_valid(self, form):
138
        self.object = form.save(commit=False)
139
140
        # HINT: validate object?
141
142
        # setting statuses and messages
143
        self.object.status = NEED_REVISION
144
        self.object.last_changed = timezone.now()
145
        self.object.save()
146
147
        if self.object.validationresult:
148
            validationresult = self.object.validationresult
149
        else:
150
            validationresult = self.validationresult_class()
151
            self.object.validationresult = validationresult
152
153
        validationresult.messages = [
154
            'Info: Data has changed, validation has to be called']
155
        validationresult.status = "Info"
156
        validationresult.save()
157
158
        # Override submission status
159
        self.object.submission.status = NEED_REVISION
160
        self.object.submission.message = (
161
            "Data has changed, validation has to be called")
162
        self.object.submission.save()
163
164
        # save object and return HttpResponseRedirect(self.get_success_url())
165
        return super().form_valid(form)
166
167
168
class DeleteMaterialMixin(OwnerMixin):
169
    """A common DeleteMixin for Material classes (Sample/Animal)"""
170
171 View Code Duplication
    def dispatch(self, request, *args, **kwargs):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
172
        handler = super(DeleteMaterialMixin, self).dispatch(
173
                request, *args, **kwargs)
174
175
        # here I've done get_queryset. Check for submission status
176
        if hasattr(self, "object") and not self.object.can_delete():
177
            message = "Cannot delete %s: submission status is: %s" % (
178
                    self.object, self.object.submission.get_status_display())
179
180
            logger.warning(message)
181
            messages.warning(
182
                request=self.request,
183
                message=message,
184
                extra_tags="alert alert-dismissible alert-warning")
185
186
            return redirect(self.object.get_absolute_url())
187
188
        return handler
189
190
    def get_success_url(self):
191
        return reverse(
192
            'submissions:edit',
193
            kwargs={'pk': self.object.submission.pk}
194
        )
195
196
197
class ListMaterialMixin(OwnerMixin):
198
    """A common ListMixin for Material classes (Sample/Animal)"""
199
200
    pass
201
202
203
def ajax_required(f):
204
    # https://stackoverflow.com/a/52271410/4385116
205
    # use a decorator to wrap a function and avoid
206
    # 'functools.partial' object has no attribute '__name__'.
207
    @wraps(f)
208
    def wrap(request, *args, **kwargs):
209
        if not request.is_ajax():
210
            return HttpResponseBadRequest()
211
212
        return f(request, *args, **kwargs)
213
214
    return wrap
215
216
217
# https://stackoverflow.com/a/13409704/4385116
218
class AjaxTemplateView(TemplateView):
219
    @method_decorator(ajax_required)
220
    def dispatch(self, *args, **kwargs):
221
        return super(AjaxTemplateView, self).dispatch(*args, **kwargs)
222
223
224
class FormInvalidMixin():
225
    def get_form_kwargs(self):
226
        kwargs = super(FormInvalidMixin, self).get_form_kwargs()
227
        kwargs['request'] = self.request
228
        return kwargs
229
230
    def form_invalid(self, form):
231
        messages.error(
232
            self.request,
233
            message="Please correct the errors below",
234
            extra_tags="alert alert-dismissible alert-danger")
235
236
        return super(FormInvalidMixin, self).form_invalid(form)
237