Completed
Push — master ( 293404...a99f81 )
by Asif
10s
created

BaseListViewMixin.get_queryset()   A

Complexity

Conditions 4

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 14
rs 9.2
cc 4
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['project_name'] = getattr(
83
            settings, 'PROJECT_NAME', 'CRUDBUILDER')
84
        return context
85
86
    @property
87
    def get_actual_signal(self):
88
        view = 'update' if self.object else 'create'
89
        if self.inlineformset:
90
            return crudbuilder_signals['inlineformset'][view]
91
        else:
92
            return crudbuilder_signals['instance'][view]
93
94
95
class BaseDetailViewMixin(CrudBuilderMixin):
96
    def get_context_data(self, **kwargs):
97
        context = super(BaseDetailViewMixin, self).get_context_data(**kwargs)
98
        context['inlineformset'] = self.inlineformset
99
        return context
100
101
102
class CreateUpdateViewMixin(CrudBuilderMixin):
103
    """Common form_valid() method for both Create and Update views"""
104
105
    def form_valid(self, form):
106
        signal = self.get_actual_signal
107
        instance = form.save(commit=False)
108
        signal.send(sender=self.model, request=self.request, instance=instance)
109
        instance.save()
110
        form.save_m2m()
111
        return super(CreateUpdateViewMixin, self).form_valid(form)
112
113
114
class BaseListViewMixin(CrudBuilderMixin):
115
    """
116
    - Search implementation for tables2 in ListView.
117
    - search_feilds will be defined in actual model
118
    - Override get_queryset method of ListView
119
    """
120
    def get_queryset(self):
121
        if self.custom_queryset:
122
            objects = self.custom_queryset(self.request, **self.kwargs)
123
        else:
124
            objects = self.model.objects.all()
125
        search = self.request.GET.get('search')
126
        if search:
127
            q_list = [
128
                Q(
129
                    ('{}__icontains'.format(field), search))
130
                for field in self.crud.search_fields
131
            ]
132
            objects = objects.filter(reduce(operator.or_, q_list))
133
        return objects.order_by('-id')
134
135
    def get_context_data(self, **kwargs):
136
        context = super(BaseListViewMixin, self).get_context_data(**kwargs)
137
        if self.custom_context:
138
            custom_context = self.custom_context(self.request, context, **kwargs)
139
            context.update(custom_context)
140
        return context
141
142
143
class InlineFormsetViewMixin(CrudBuilderMixin):
144
    def get_context_data(self, **kwargs):
145
        context = super(
146
            InlineFormsetViewMixin, self).get_context_data(**kwargs)
147
        if self.request.POST:
148
            context['inlineformset'] = self.inlineformset(
149
                self.request.POST,
150
                instance=self.object
151
            )
152
        else:
153
            context['inlineformset'] = self.inlineformset(
154
                instance=self.object
155
            )
156
        return context
157
158
    def form_valid(self, form):
159
        context = self.get_context_data()
160
        inlineformset = context['inlineformset']
161
162
        if inlineformset.is_valid():
163
            parent = form.save(commit=False)
164
            inlineformset.instance = parent
165
            children = inlineformset.save(commit=False)
166
167
            # execute post signals
168
            signal = self.get_actual_signal
169
            signal.send(
170
                sender=self.model,
171
                request=self.request,
172
                parent=parent,
173
                children=children)
174
175
            parent.save()
176
            inlineformset.save()
177
            inlineformset.save_m2m()
178
179
            return HttpResponseRedirect(self.success_url)
180
        else:
181
            messages.error(
182
                self.request, inlineformset.non_form_errors())
183
            return self.render_to_response(
184
                self.get_context_data(form=form, inlineformset=inlineformset)
185
            )
186