1
|
|
|
from django.core.urlresolvers import reverse_lazy |
2
|
|
|
from django.forms.models import modelform_factory |
3
|
|
|
from django.views.generic import( |
4
|
|
|
DetailView, |
5
|
|
|
CreateView, |
6
|
|
|
UpdateView, |
7
|
|
|
DeleteView |
8
|
|
|
) |
9
|
|
|
from django_tables2 import SingleTableView |
10
|
|
|
|
11
|
|
|
from crudbuilder.mixins import( |
12
|
|
|
CrudBuilderMixin, |
13
|
|
|
BaseListViewMixin, |
14
|
|
|
CreateUpdateViewMixin |
15
|
|
|
) |
16
|
|
|
from crudbuilder.abstract import BaseBuilder |
17
|
|
|
from crudbuilder.tables import TableBuilder |
18
|
|
|
from crudbuilder.helpers import model_class_form, plural |
19
|
|
|
|
20
|
|
|
|
21
|
|
|
class ViewBuilder(BaseBuilder): |
22
|
|
|
"""View builder which returns all the CRUD class based views""" |
23
|
|
|
|
24
|
|
|
def __init__(self, *args, **kwargs): |
25
|
|
|
super(ViewBuilder, self).__init__(*args, **kwargs) |
26
|
|
|
self.classes = {} |
27
|
|
|
|
28
|
|
|
def generate_crud(self): |
29
|
|
|
self.generate_list_view() |
30
|
|
|
self.generate_create_view() |
31
|
|
|
self.generate_detail_view() |
32
|
|
|
self.generate_update_view() |
33
|
|
|
self.generate_delete_view() |
34
|
|
|
|
35
|
|
|
def get_actual_form(self): |
36
|
|
|
if self.custom_modelform: |
37
|
|
|
return self.custom_modelform |
38
|
|
|
else: |
39
|
|
|
return self.generate_modelform() |
40
|
|
|
|
41
|
|
|
def get_actual_table(self): |
42
|
|
|
if self.custom_table2: |
43
|
|
|
return self.custom_table2 |
44
|
|
|
else: |
45
|
|
|
table_builder = TableBuilder(self.app, self.model, self.crud) |
46
|
|
|
return table_builder.generate_table() |
47
|
|
|
|
48
|
|
|
def generate_modelform(self): |
49
|
|
|
"""Generate modelform from Django modelform_factory""" |
50
|
|
|
|
51
|
|
|
model_class = self.get_model_class |
52
|
|
|
excludes = self.modelform_excludes if self.modelform_excludes else [] |
53
|
|
|
_ObjectForm = modelform_factory(model_class, exclude=excludes) |
54
|
|
|
return _ObjectForm |
55
|
|
|
|
56
|
|
|
def get_template(self, tname): |
57
|
|
|
""" |
58
|
|
|
- Get custom template from CRUD class, if it is defined in it |
59
|
|
|
- No custom template in CRUD class, then use the default template |
60
|
|
|
""" |
61
|
|
|
if self.custom_templates and self.custom_templates.get(tname, None): |
62
|
|
|
return self.custom_templates.get(tname) |
63
|
|
|
else: |
64
|
|
|
return 'object_{}.html'.format(tname) |
65
|
|
|
|
66
|
|
|
def generate_list_view(self): |
67
|
|
|
"""Generate class based view for ListView""" |
68
|
|
|
|
69
|
|
|
name = model_class_form(self.model + 'ListView') |
70
|
|
|
list_args = dict( |
71
|
|
|
model=self.get_model_class, |
72
|
|
|
context_object_name=plural(self.model), |
73
|
|
|
template_name=self.get_template('list'), |
74
|
|
|
table_class=self.get_actual_table(), |
75
|
|
|
context_table_name='table_objects', |
76
|
|
|
crud=self.crud, |
77
|
|
|
permission_required=self.view_permission('list'), |
78
|
|
|
table_pagination=self.tables2_pagination or 10 |
79
|
|
|
) |
80
|
|
|
|
81
|
|
|
list_class = type( |
82
|
|
|
name, |
83
|
|
|
(BaseListViewMixin, SingleTableView), |
84
|
|
|
list_args |
85
|
|
|
) |
86
|
|
|
self.classes[name] = list_class |
87
|
|
|
return list_class |
88
|
|
|
|
89
|
|
|
def generate_create_view(self): |
|
|
|
|
90
|
|
|
"""Generate class based view for CreateView""" |
91
|
|
|
|
92
|
|
|
name = model_class_form(self.model + 'CreateView') |
93
|
|
|
create_args = dict( |
94
|
|
|
form_class=self.get_actual_form(), |
95
|
|
|
model=self.get_model_class, |
96
|
|
|
template_name=self.get_template('create'), |
97
|
|
|
permission_required=self.view_permission('create'), |
98
|
|
|
success_url=reverse_lazy('{}-{}-list'.format(self.app, self.model)) |
99
|
|
|
) |
100
|
|
|
|
101
|
|
|
create_class = type(name, (CreateUpdateViewMixin, CreateView), create_args) |
102
|
|
|
self.classes[name] = create_class |
103
|
|
|
return create_class |
104
|
|
|
|
105
|
|
|
def generate_detail_view(self): |
106
|
|
|
"""Generate class based view for DetailView""" |
107
|
|
|
|
108
|
|
|
name = model_class_form(self.model + 'DetailView') |
109
|
|
|
detail_args = dict( |
110
|
|
|
model=self.get_model_class, |
111
|
|
|
template_name=self.get_template('detail'), |
112
|
|
|
permission_required=self.view_permission('detail') |
113
|
|
|
) |
114
|
|
|
|
115
|
|
|
detail_class = type(name, (CrudBuilderMixin, DetailView), detail_args) |
116
|
|
|
self.classes[name] = detail_class |
117
|
|
|
return detail_class |
118
|
|
|
|
119
|
|
|
def generate_update_view(self): |
|
|
|
|
120
|
|
|
"""Generate class based view for UpdateView""" |
121
|
|
|
|
122
|
|
|
name = model_class_form(self.model + 'UpdateView') |
123
|
|
|
update_args = dict( |
124
|
|
|
form_class=self.get_actual_form(), |
125
|
|
|
model=self.get_model_class, |
126
|
|
|
template_name=self.get_template('update'), |
127
|
|
|
permission_required=self.view_permission('update'), |
128
|
|
|
success_url=reverse_lazy('{}-{}-list'.format(self.app, self.model)) |
129
|
|
|
) |
130
|
|
|
|
131
|
|
|
update_class = type( |
132
|
|
|
name, |
133
|
|
|
(CreateUpdateViewMixin, UpdateView), |
134
|
|
|
update_args |
135
|
|
|
) |
136
|
|
|
self.classes[name] = update_class |
137
|
|
|
return update_class |
138
|
|
|
|
139
|
|
|
def generate_delete_view(self): |
140
|
|
|
"""Generate class based view for DeleteView""" |
141
|
|
|
|
142
|
|
|
name = model_class_form(self.model + 'DeleteView') |
143
|
|
|
delete_args = dict( |
144
|
|
|
model=self.get_model_class, |
145
|
|
|
template_name=self.get_template('delete'), |
146
|
|
|
permission_required=self.view_permission('delete'), |
147
|
|
|
success_url=reverse_lazy('{}-{}-list'.format(self.app, self.model)) |
148
|
|
|
) |
149
|
|
|
|
150
|
|
|
delete_class = type(name, (CrudBuilderMixin, DeleteView), delete_args) |
151
|
|
|
self.classes[name] = delete_class |
152
|
|
|
return delete_class |
153
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.