Completed
Push — master ( 0e6eac...543ed2 )
by Asif
01:14
created

CreateUpdateViewMixin.get_form_kwargs()   A

Complexity

Conditions 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 2
1
import operator
2
import six
3
from django.db.models import Q
4
from django.http import HttpResponseRedirect
5
from django.contrib.auth.views import redirect_to_login
6
from django.contrib.auth import REDIRECT_FIELD_NAME
7
from django.conf import settings
8
from django.contrib import messages
9
10
from crudbuilder.helpers import plural
11
from crudbuilder.signals import crudbuilder_signals
12
13
if six.PY3:
14
    from functools import reduce
15
16
17
class LoginRequiredMixin(object):
18
    """
19
    View mixin which verifies that login required for the crud builder
20
    """
21
    login_url = settings.LOGIN_URL
22
    redirect_field_name = REDIRECT_FIELD_NAME  # Set by django.contrib.auth
23
24
    def handle_login_required(self, request):
25
        return redirect_to_login(
26
            request.get_full_path(),
27
            self.login_url,
28
            self.redirect_field_name)
29
30
    def dispatch(self, request, *args, **kwargs):
31
        global_login_required = getattr(
32
            settings, 'LOGIN_REQUIRED_FOR_CRUD', False)
33
34
        if global_login_required or self.login_required:
35
            if not request.user.is_authenticated():
36
                return self.handle_login_required(request)
37
38
        return super(LoginRequiredMixin, self).dispatch(
39
            request, *args, **kwargs)
40
41
42
class PermissionRequiredMixin(object):
43
    """
44
    View mixin which verifies that the logged in user has the specified
45
    permission.
46
    """
47
    def check_permissions(self, request):
48
        perms = self.permissions
49
        result = request.user.has_perm(perms) if perms else True
50
        return result
51
52
    def dispatch(self, request, *args, **kwargs):
53
        has_permission = self.check_permissions(request)
54
        global_permission_required = getattr(
55
            settings, 'PERMISSION_REQUIRED_FOR_CRUD', False)
56
57
        if global_permission_required or self.permission_required:
58
            if not has_permission:
59
                return redirect_to_login(
60
                    request.get_full_path(),
61
                    settings.LOGIN_URL,
62
                    REDIRECT_FIELD_NAME)
63
64
        return super(PermissionRequiredMixin, self).dispatch(
65
            request, *args, **kwargs)
66
67
68
class CrudBuilderMixin(LoginRequiredMixin, PermissionRequiredMixin):
69
    """
70
    - Mixin to provide additional context data for the templates
71
    - app_label : return app_label for CRUD model
72
    - actual_model_name : returns the actual model name (person -> person)
73
    - pluralized_model_name : return the pluralized_model_name
74
    (person -> people)
75
    """
76
    def get_context_data(self, **kwargs):
77
        context = super(CrudBuilderMixin, self).get_context_data(**kwargs)
78
        model = context['view'].model
79
        context['app_label'] = model._meta.app_label
80
        context['actual_model_name'] = model.__name__.lower()
81
        context['pluralized_model_name'] = plural(model.__name__.lower())
82
        context['verbose_model_name'] = model._meta.verbose_name
83
        context['verbose_model_name_plural'] = model._meta.verbose_name_plural
84
        context['project_name'] = getattr(
85
            settings, 'PROJECT_NAME', 'CRUDBUILDER')
86
        return context
87
88
    @property
89
    def get_actual_signal(self):
90
        view = 'update' if self.object else 'create'
91
        if self.inlineformset:
92
            return crudbuilder_signals['inlineformset'][view]
93
        else:
94
            return crudbuilder_signals['instance'][view]
95
96
97
class BaseDetailViewMixin(CrudBuilderMixin):
98
    def get_context_data(self, **kwargs):
99
        context = super(BaseDetailViewMixin, self).get_context_data(**kwargs)
100
        context['inlineformset'] = self.inlineformset
101
        return context
102
103
104
class CreateUpdateViewMixin(CrudBuilderMixin):
105
    """Common form_valid() method for both Create and Update views"""
106
    def get_form_kwargs(self):
107
        kwargs = super(CreateUpdateViewMixin, self).get_form_kwargs()
108
        if self.custom_form:
109
            kwargs.update({'request': self.request})
110
        return kwargs
111
112
    def form_valid(self, form):
113
        signal = self.get_actual_signal
114
        instance = form.save(commit=False)
115
        signal.send(sender=self.model, request=self.request, instance=instance)
116
        instance.save()
117
        form.save_m2m()
118
        return super(CreateUpdateViewMixin, self).form_valid(form)
119
120
121
class BaseListViewMixin(CrudBuilderMixin):
122
    """
123
    - Search implementation for tables2 in ListView.
124
    - search_fields will be defined in actual model
125
    - Override get_queryset method of ListView
126
    """
127
    def get_queryset(self):
128
        if self.custom_queryset:
129
            objects = self.custom_queryset(self.request, **self.kwargs)
130
        else:
131
            objects = self.model.objects.all()
132
        search = self.request.GET.get('search')
133
        if search:
134
            q_list = [
135
                Q(
136
                    ('{}__icontains'.format(field), search))
137
                for field in self.crud.search_fields
138
            ]
139
            objects = objects.filter(reduce(operator.or_, q_list))
140
        return objects.order_by('-id')
141
142
    def get_context_data(self, **kwargs):
143
        context = super(BaseListViewMixin, self).get_context_data(**kwargs)
144
        if self.custom_context:
145
            custom_context = self.custom_context(self.request, context, **kwargs)
146
            context.update(custom_context)
147
        return context
148
149
150
class InlineFormsetViewMixin(CrudBuilderMixin):
151
    def get_context_data(self, **kwargs):
152
        context = super(
153
            InlineFormsetViewMixin, self).get_context_data(**kwargs)
154
        if self.request.POST:
155
            context['inlineformset'] = self.inlineformset(
156
                self.request.POST,
157
                instance=self.object
158
            )
159
        else:
160
            context['inlineformset'] = self.inlineformset(
161
                instance=self.object
162
            )
163
        return context
164
165
    def form_valid(self, form):
166
        context = self.get_context_data()
167
        inlineformset = context['inlineformset']
168
169
        if inlineformset.is_valid():
170
            parent = form.save(commit=False)
171
            inlineformset.instance = parent
172
            children = inlineformset.save(commit=False)
173
174
            # execute post signals
175
            signal = self.get_actual_signal
176
            signal.send(
177
                sender=self.model,
178
                request=self.request,
179
                parent=parent,
180
                children=children)
181
182
            parent.save()
183
            inlineformset.save()
184
            inlineformset.save_m2m()
185
186
            return HttpResponseRedirect(self.success_url)
187
        else:
188
            messages.error(
189
                self.request, inlineformset.non_form_errors())
190
            return self.render_to_response(
191
                self.get_context_data(form=form, inlineformset=inlineformset)
192
            )
193