educommon 3.12.0__py3-none-any.whl → 3.13.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. educommon/__init__.py +0 -1
  2. educommon/about/ui/actions.py +16 -30
  3. educommon/about/ui/ui.py +3 -12
  4. educommon/about/utils.py +6 -5
  5. educommon/async_task/__init__.py +0 -1
  6. educommon/async_task/actions.py +18 -13
  7. educommon/async_task/apps.py +4 -0
  8. educommon/async_task/locker.py +2 -5
  9. educommon/async_task/migrations/0001_initial.py +55 -9
  10. educommon/async_task/migrations/0002_task_type_and_status_data.py +94 -89
  11. educommon/async_task/migrations/0003_alter_runningtask_options.py +0 -1
  12. educommon/async_task/models.py +9 -6
  13. educommon/async_task/tasks.py +11 -7
  14. educommon/async_task/ui.py +16 -35
  15. educommon/async_tasks/__init__.py +0 -1
  16. educommon/async_tasks/apps.py +4 -0
  17. educommon/async_tasks/locks.py +11 -21
  18. educommon/async_tasks/migrations/0001_initial.py +68 -8
  19. educommon/async_tasks/migrations/0002_load_initial_data.py +0 -1
  20. educommon/async_tasks/models.py +9 -29
  21. educommon/async_tasks/tasks.py +25 -54
  22. educommon/audit_log/__init__.py +1 -0
  23. educommon/audit_log/actions.py +27 -36
  24. educommon/audit_log/app_meta.py +7 -4
  25. educommon/audit_log/apps.py +44 -29
  26. educommon/audit_log/constants.py +7 -4
  27. educommon/audit_log/error_log/actions.py +1 -3
  28. educommon/audit_log/helpers.py +2 -4
  29. educommon/audit_log/management/commands/reinstall_audit_log.py +11 -7
  30. educommon/audit_log/migrations/0001_initial.py +91 -16
  31. educommon/audit_log/migrations/0002_install_audit_log.py +13 -13
  32. educommon/audit_log/migrations/0003_logproxy.py +1 -3
  33. educommon/audit_log/migrations/0004_reinstall_audit_log.py +1 -4
  34. educommon/audit_log/migrations/0005_postgresql_error.py +4 -2
  35. educommon/audit_log/migrations/0006_auto_20200806_1707.py +3 -4
  36. educommon/audit_log/migrations/0007_create_selective_tables_function.py +8 -5
  37. educommon/audit_log/migrations/0008_table_logged.py +0 -1
  38. educommon/audit_log/migrations/0009_reinstall_audit_log.py +0 -1
  39. educommon/audit_log/models.py +36 -42
  40. educommon/audit_log/permissions.py +11 -9
  41. educommon/audit_log/proxies.py +12 -23
  42. educommon/audit_log/ui.py +18 -15
  43. educommon/audit_log/utils/__init__.py +28 -60
  44. educommon/audit_log/utils/operations.py +16 -2
  45. educommon/auth/__init__.py +0 -3
  46. educommon/auth/rbac/__init__.py +2 -4
  47. educommon/auth/rbac/actions.py +148 -145
  48. educommon/auth/rbac/app_meta.py +9 -6
  49. educommon/auth/rbac/backends/base.py +2 -8
  50. educommon/auth/rbac/backends/caching.py +27 -37
  51. educommon/auth/rbac/backends/simple.py +1 -4
  52. educommon/auth/rbac/checker.py +1 -3
  53. educommon/auth/rbac/management/commands/rbac.py +6 -11
  54. educommon/auth/rbac/manager.py +18 -47
  55. educommon/auth/rbac/migrations/0001_initial.py +73 -12
  56. educommon/auth/rbac/migrations/0002_model_modifier_metaclass_fix.py +7 -6
  57. educommon/auth/rbac/migrations/0003_permission_hidden.py +1 -5
  58. educommon/auth/rbac/migrations/0004_auto_20171024_1245.py +26 -19
  59. educommon/auth/rbac/models.py +63 -68
  60. educommon/auth/rbac/permissions.py +6 -7
  61. educommon/auth/rbac/ui.py +83 -84
  62. educommon/auth/rbac/utils.py +10 -11
  63. educommon/auth/rbac/validators.py +4 -5
  64. educommon/auth/simple_auth/__init__.py +1 -5
  65. educommon/auth/simple_auth/actions.py +79 -92
  66. educommon/auth/simple_auth/app_meta.py +2 -9
  67. educommon/auth/simple_auth/checkers.py +3 -3
  68. educommon/auth/simple_auth/migrations/0001_initial.py +23 -4
  69. educommon/auth/simple_auth/validators.py +0 -1
  70. educommon/contingent/actions.py +7 -7
  71. educommon/contingent/app_meta.py +1 -4
  72. educommon/contingent/base.py +10 -15
  73. educommon/contingent/catalogs.py +424 -540
  74. educommon/contingent/contingent_plugin/actions.py +4 -15
  75. educommon/contingent/contingent_plugin/apps.py +10 -4
  76. educommon/contingent/contingent_plugin/migrations/0001_initial.py +5 -6
  77. educommon/contingent/contingent_plugin/migrations/0002_add_contingent_model_deleted.py +6 -11
  78. educommon/contingent/contingent_plugin/model_views.py +2 -12
  79. educommon/contingent/contingent_plugin/models.py +2 -7
  80. educommon/contingent/contingent_plugin/observer.py +14 -13
  81. educommon/contingent/contingent_plugin/plugin_meta.py +1 -3
  82. educommon/contingent/contingent_plugin/storage.py +8 -7
  83. educommon/contingent/contingent_plugin/utils.py +6 -6
  84. educommon/django/db/fields.py +72 -86
  85. educommon/django/db/migration/__init__.py +3 -7
  86. educommon/django/db/migration/operations.py +29 -51
  87. educommon/django/db/mixins/__init__.py +16 -10
  88. educommon/django/db/mixins/date_interval.py +47 -75
  89. educommon/django/db/mixins/validation.py +26 -26
  90. educommon/django/db/model_view/__init__.py +18 -22
  91. educommon/django/db/models.py +9 -8
  92. educommon/django/db/observer.py +9 -27
  93. educommon/django/db/partitioning/__init__.py +66 -92
  94. educommon/django/db/partitioning/management/commands/apply_partitioning.py +3 -13
  95. educommon/django/db/partitioning/management/commands/clear_table.py +18 -14
  96. educommon/django/db/partitioning/management/commands/split_table.py +18 -13
  97. educommon/django/db/routers.py +6 -15
  98. educommon/django/db/signals.py +149 -2
  99. educommon/django/db/utils.py +14 -19
  100. educommon/django/db/validators/__init__.py +1 -0
  101. educommon/django/db/validators/simple.py +72 -100
  102. educommon/django/storages/atcfs/api.py +39 -53
  103. educommon/django/storages/atcfs/app_meta.py +1 -1
  104. educommon/django/storages/atcfs/management/commands/atcfs_migrate.py +42 -55
  105. educommon/django/storages/atcfs/models.py +0 -3
  106. educommon/django/storages/atcfs/monkey_patching.py +18 -12
  107. educommon/django/storages/atcfs/storage.py +14 -23
  108. educommon/extjs/fields/input_params.py +15 -45
  109. educommon/importer/XLSReader.py +143 -241
  110. educommon/importer/__init__.py +86 -4
  111. educommon/importer/api.py +53 -84
  112. educommon/importer/constants.py +4 -14
  113. educommon/importer/loggers.py +16 -26
  114. educommon/importer/proxy.py +131 -176
  115. educommon/importer/proxy_import.py +11 -12
  116. educommon/importer/report.py +4 -6
  117. educommon/importer/ui.py +32 -26
  118. educommon/importer/validators.py +4 -7
  119. educommon/integration_entities/helpers.py +14 -18
  120. educommon/ioc/__init__.py +3 -6
  121. educommon/logger/loggers.py +10 -14
  122. educommon/m3/__init__.py +20 -38
  123. educommon/m3/extensions/__init__.py +1 -0
  124. educommon/m3/extensions/listeners/__init__.py +22 -38
  125. educommon/m3/extensions/listeners/delete_check/listeners.py +31 -41
  126. educommon/m3/extensions/listeners/delete_check/mixins.py +20 -25
  127. educommon/m3/extensions/listeners/delete_check/signals.py +2 -2
  128. educommon/m3/extensions/listeners/delete_check/ui.py +15 -14
  129. educommon/m3/extensions/listeners/delete_check/utils.py +9 -11
  130. educommon/m3/extensions/ui.py +15 -33
  131. educommon/m3/transaction_context.py +17 -19
  132. educommon/objectpack/actions.py +70 -88
  133. educommon/objectpack/apps.py +5 -0
  134. educommon/objectpack/filters.py +9 -15
  135. educommon/objectpack/ui.py +59 -77
  136. educommon/report/__init__.py +9 -5
  137. educommon/report/actions.py +29 -32
  138. educommon/report/constructor/__init__.py +5 -8
  139. educommon/report/constructor/app_meta.py +1 -3
  140. educommon/report/constructor/apps.py +1 -0
  141. educommon/report/constructor/base.py +33 -80
  142. educommon/report/constructor/builders/excel/_base.py +138 -286
  143. educommon/report/constructor/builders/excel/_header.py +2 -9
  144. educommon/report/constructor/builders/excel/product.py +13 -34
  145. educommon/report/constructor/builders/excel/with_merged_cells.py +18 -14
  146. educommon/report/constructor/config.py +2 -0
  147. educommon/report/constructor/editor/actions.py +101 -215
  148. educommon/report/constructor/editor/ui.py +71 -93
  149. educommon/report/constructor/exceptions.py +6 -12
  150. educommon/report/constructor/migrations/0001_initial.py +36 -44
  151. educommon/report/constructor/migrations/0002_report_filters.py +86 -72
  152. educommon/report/constructor/migrations/0003_reportfilter_exclude.py +5 -5
  153. educommon/report/constructor/migrations/0004_reportfilter_fields.py +22 -18
  154. educommon/report/constructor/migrations/0005_reportcolumn_visible.py +5 -4
  155. educommon/report/constructor/migrations/0006_reportsorting.py +21 -17
  156. educommon/report/constructor/migrations/0007_include_available_units.py +14 -14
  157. educommon/report/constructor/migrations/0008_auto_20170407_1318.py +4 -5
  158. educommon/report/constructor/migrations/0009_auto_20180405_0642.py +1 -4
  159. educommon/report/constructor/migrations/0010_add_aggregate_fields.py +7 -8
  160. educommon/report/constructor/mixins.py +14 -15
  161. educommon/report/constructor/models.py +76 -124
  162. educommon/report/constructor/utils.py +3 -8
  163. educommon/report/constructor/validators.py +1 -3
  164. educommon/report/reporter.py +25 -43
  165. educommon/report/utils.py +14 -40
  166. educommon/rest/actions.py +7 -11
  167. educommon/rest/context.py +6 -16
  168. educommon/rest/controllers.py +10 -10
  169. educommon/rest/mixins.py +29 -27
  170. educommon/secure_media/app_meta.py +9 -9
  171. educommon/utils/__init__.py +3 -2
  172. educommon/utils/caching.py +1 -3
  173. educommon/utils/conversion.py +1 -3
  174. educommon/utils/crypto.py +1 -2
  175. educommon/utils/date.py +13 -26
  176. educommon/utils/db/__init__.py +17 -26
  177. educommon/utils/db/postgresql.py +1 -4
  178. educommon/utils/fonts/__init__.py +3 -4
  179. educommon/utils/licence/__init__.py +5 -16
  180. educommon/utils/misc.py +9 -18
  181. educommon/utils/object_grid.py +55 -62
  182. educommon/utils/phone_number/modelfields.py +1 -3
  183. educommon/utils/phone_number/phone_number.py +5 -8
  184. educommon/utils/phone_number/validators.py +8 -23
  185. educommon/utils/plugins.py +15 -28
  186. educommon/utils/registry.py +2 -1
  187. educommon/utils/seqtools.py +1 -3
  188. educommon/utils/serializer.py +9 -16
  189. educommon/utils/storage.py +3 -2
  190. educommon/utils/system.py +1 -3
  191. educommon/utils/system_app/management/commands/delete_objects.py +17 -34
  192. educommon/utils/ui.py +87 -84
  193. educommon/utils/xml/__init__.py +2 -7
  194. educommon/utils/xml/resolver.py +1 -0
  195. educommon/ws_log/actions.py +31 -76
  196. educommon/ws_log/base.py +6 -20
  197. educommon/ws_log/migrations/0001_initial.py +25 -8
  198. educommon/ws_log/migrations/0002_auto_20160628_1334.py +0 -1
  199. educommon/ws_log/migrations/0003_add_fields_to_smev_logs.py +20 -4
  200. educommon/ws_log/migrations/0004_auto_20160727_1600.py +7 -6
  201. educommon/ws_log/migrations/0005_auto_20161130_1615.py +14 -4
  202. educommon/ws_log/migrations/0006_auto_20170327_1027.py +3 -2
  203. educommon/ws_log/migrations/0007_auto_20180607_1040.py +8 -9
  204. educommon/ws_log/migrations/0008_auto_20180713_1445.py +23 -10
  205. educommon/ws_log/migrations/0009_auto_20201130_1553.py +7 -2
  206. educommon/ws_log/models.py +21 -35
  207. educommon/ws_log/provider.py +2 -1
  208. educommon/ws_log/report.py +8 -13
  209. educommon/ws_log/smev/applications.py +12 -27
  210. educommon/ws_log/smev/exceptions.py +2 -3
  211. educommon/ws_log/ui.py +32 -32
  212. educommon/ws_log/utils.py +1 -3
  213. educommon-3.13.2.dist-info/METADATA +57 -0
  214. educommon-3.13.2.dist-info/RECORD +354 -0
  215. {educommon-3.12.0.dist-info → educommon-3.13.2.dist-info}/WHEEL +1 -1
  216. educommon/utils/patches.py +0 -27
  217. educommon/version.conf +0 -11
  218. educommon-3.12.0.dist-info/METADATA +0 -47
  219. educommon-3.12.0.dist-info/RECORD +0 -357
  220. educommon-3.12.0.dist-info/dependency_links.txt +0 -1
  221. {educommon-3.12.0.dist-info → educommon-3.13.2.dist-info}/top_level.txt +0 -0
@@ -106,23 +106,15 @@ class ColumnsAction(BaseAction):
106
106
  if context.parent_column_name == '-1':
107
107
  context.parent_column_name = None
108
108
 
109
- data_source = registry.get(
110
- context.data_source_name
111
- ).get_data_source_descriptor()
109
+ data_source = registry.get(context.data_source_name).get_data_source_descriptor()
112
110
 
113
111
  if context.parent_column_name:
114
- parent_column = ColumnDescriptor.create(
115
- data_source.model, context.parent_column_name, data_source
116
- )
112
+ parent_column = ColumnDescriptor.create(data_source.model, context.parent_column_name, data_source)
117
113
  columns = parent_column.get_nested_columns()
118
114
  else:
119
- columns = tuple(
120
- data_source.get_available_columns()
121
- )
115
+ columns = tuple(data_source.get_available_columns())
122
116
 
123
- return PreJsonResult(tuple(
124
- map(ColumnsAction._get_column_params, columns)
125
- ))
117
+ return PreJsonResult(tuple(map(ColumnsAction._get_column_params, columns)))
126
118
 
127
119
 
128
120
  _BUILDERS_PACKAGE = 'educommon.report.constructor.builders'
@@ -132,10 +124,8 @@ class BuildAction(BaseAction):
132
124
  """Сборка отчета на основе указанного шаблона."""
133
125
 
134
126
  _builders = {
135
- ReportTemplate.EXCEL_SIMPLE:
136
- _BUILDERS_PACKAGE + '.excel.product.ReportBuilder',
137
- ReportTemplate.EXCEL_MERGED:
138
- _BUILDERS_PACKAGE + '.excel.with_merged_cells.ReportBuilder',
127
+ ReportTemplate.EXCEL_SIMPLE: f'{_BUILDERS_PACKAGE}.excel.product.ReportBuilder',
128
+ ReportTemplate.EXCEL_MERGED: f'{_BUILDERS_PACKAGE}.excel.with_merged_cells.ReportBuilder',
139
129
  }
140
130
 
141
131
  def context_declaration(self):
@@ -147,9 +137,7 @@ class BuildAction(BaseAction):
147
137
  def _get_report_template(self, request, context):
148
138
  # Загрузка шаблона
149
139
  try:
150
- return ReportTemplate.objects.get(
151
- pk=get_id_value(context, self.parent)
152
- )
140
+ return ReportTemplate.objects.get(pk=get_id_value(context, self.parent))
153
141
  except ReportTemplate.DoesNotExist:
154
142
  raise ApplicationLogicException(self.parent.MSG_DOESNOTEXISTS)
155
143
 
@@ -158,41 +146,29 @@ class BuildAction(BaseAction):
158
146
  # шаблоне.
159
147
  if report_template.data_source_name not in registry:
160
148
  raise ApplicationLogicException(
161
- 'Источник данных {} не существует.'
162
- .format(report_template.data_source_name)
149
+ 'Источник данных {} не существует.'.format(report_template.data_source_name)
163
150
  )
164
151
 
165
- data_source = registry.get(
166
- report_template.data_source_name
167
- ).get_data_source_descriptor()
152
+ data_source = registry.get(report_template.data_source_name).get_data_source_descriptor()
168
153
 
169
154
  if ReportInfo(report_template).ignored_columns_ids:
170
- raise ApplicationLogicException(
171
- 'Некоторые колонки шаблона неактуальны, '
172
- 'требуется редактирование'
173
- )
155
+ raise ApplicationLogicException('Некоторые колонки шаблона неактуальны, требуется редактирование')
174
156
 
175
157
  # Проверка доступности данных для всех столбцов шаблона отчета.
176
158
  try:
177
- for col_name in report_template.columns.values_list(
178
- 'name', flat=True):
159
+ for col_name in report_template.columns.values_list('name', flat=True):
179
160
  if data_source.is_column_ignored(col_name):
180
161
  continue
181
162
  data_source.get_column_descriptor(col_name)
182
163
  except FieldDoesNotExist as error:
183
- raise ApplicationLogicException(
184
- 'Колонка {} недоступна'.format(str(error))
185
- )
164
+ raise ApplicationLogicException('Колонка {} недоступна'.format(str(error)))
186
165
 
187
166
  def _check_params(self, request, context, report_template):
188
167
  """Возвращает True, если параметры сборки указаны верно."""
189
168
  if context.format is None:
190
169
  return report_template.format in self._builders
191
170
 
192
- if (
193
- report_template.format == ReportTemplate.USER_DEFINED and
194
- context.format in self._builders
195
- ):
171
+ if report_template.format == ReportTemplate.USER_DEFINED and context.format in self._builders:
196
172
  return True
197
173
 
198
174
  return False
@@ -206,15 +182,19 @@ class BuildAction(BaseAction):
206
182
  data=ReportTemplate.FORMAT_CHOICES[1:],
207
183
  )
208
184
 
209
- win.form.items.extend(anchor100(
210
- win.field__format,
211
- ))
185
+ win.form.items.extend(
186
+ anchor100(
187
+ win.field__format,
188
+ )
189
+ )
212
190
 
213
- win.set_params(dict(
214
- form_url=self.get_absolute_url(),
215
- height=100,
216
- title='Параметры сборки',
217
- ))
191
+ win.set_params(
192
+ dict(
193
+ form_url=self.get_absolute_url(),
194
+ height=100,
195
+ title='Параметры сборки',
196
+ )
197
+ )
218
198
 
219
199
  return ExtUIScriptResult(win, context)
220
200
 
@@ -231,13 +211,12 @@ class BuildAction(BaseAction):
231
211
  'object_id': user.id,
232
212
  'content_type': content_type,
233
213
  'report_template_id': report_template_id,
234
- 'format': context.format or None
214
+ 'format': context.format or None,
235
215
  }
236
216
  report_constructor_config.async_task.apply_async(None, params)
237
217
 
238
218
  return OperationResult(
239
- message='Внимание! Задача поставлена в очередь! Результаты '
240
- 'будут доступны в реестре Асинхронных задач.'
219
+ message='Внимание! Задача поставлена в очередь! Результаты будут доступны в реестре Асинхронных задач.'
241
220
  )
242
221
 
243
222
  def run(self, request, context):
@@ -262,9 +241,7 @@ class ReportInfo:
262
241
  :type report_template:
263
242
  educommon.report.constructor.models.ReportTemplate
264
243
  """
265
- assert isinstance(report_template, ReportTemplate), type(
266
- report_template
267
- )
244
+ assert isinstance(report_template, ReportTemplate), type(report_template)
268
245
 
269
246
  self.report_template = report_template
270
247
 
@@ -274,9 +251,7 @@ class ReportInfo:
274
251
 
275
252
  :rtype: educommon.report.constructor.base.ModelDataSourceDescriptor
276
253
  """
277
- data_source = registry.get(
278
- self.report_template.data_source_name
279
- ).get_data_source_descriptor()
254
+ data_source = registry.get(self.report_template.data_source_name).get_data_source_descriptor()
280
255
  return data_source
281
256
 
282
257
  @cached_property
@@ -288,10 +263,8 @@ class ReportInfo:
288
263
  :rtype: set
289
264
  """
290
265
  ignored_columns = set()
291
- for col_id, col_name in self.report_template.columns.values_list(
292
- 'id', 'name'):
293
- if (self._data_source.is_column_ignored(col_name) or
294
- not self._data_source.is_column_exist(col_name)):
266
+ for col_id, col_name in self.report_template.columns.values_list('id', 'name'):
267
+ if self._data_source.is_column_ignored(col_name) or not self._data_source.is_column_exist(col_name):
295
268
  ignored_columns.add(col_id)
296
269
 
297
270
  return ignored_columns
@@ -304,10 +277,7 @@ class ReportInfo:
304
277
  """
305
278
  columns = self.report_template.columns.order_by('index')
306
279
 
307
- return OrderedDict(
308
- (report_column.id, report_column)
309
- for report_column in columns
310
- )
280
+ return OrderedDict((report_column.id, report_column) for report_column in columns)
311
281
 
312
282
  @cached_property
313
283
  def _report_columns_by_name(self):
@@ -315,10 +285,7 @@ class ReportInfo:
315
285
 
316
286
  :rtype: collections.OrderedDict
317
287
  """
318
- return OrderedDict(
319
- (report_column.name, report_column)
320
- for report_column in self._report_columns_by_id.values()
321
- )
288
+ return OrderedDict((report_column.name, report_column) for report_column in self._report_columns_by_id.values())
322
289
 
323
290
  @cached_property
324
291
  def _field_descriptors(self):
@@ -353,9 +320,7 @@ class ReportInfo:
353
320
 
354
321
  for descriptor in self._field_descriptors.values():
355
322
  if not descriptor.is_root():
356
- hierarchy[descriptor.parent.full_accessor_name].append(
357
- descriptor
358
- )
323
+ hierarchy[descriptor.parent.full_accessor_name].append(descriptor)
359
324
 
360
325
  return hierarchy
361
326
 
@@ -370,20 +335,13 @@ class ReportInfo:
370
335
  full_name=full_accessor_name,
371
336
  title=descriptor.title,
372
337
  leaf=not descriptor.has_nested_columns(),
373
- nested=tuple(
374
- self._get_descriptor_data(descriptor)
375
- for descriptor in nested_descriptors
376
- ),
338
+ nested=tuple(self._get_descriptor_data(descriptor) for descriptor in nested_descriptors),
377
339
  )
378
340
  column = self._report_columns_by_name.get(full_accessor_name, None)
379
341
  column_id = getattr(column, 'id', 0)
380
- result['is_fake'] = (
381
- not column_id or column_id in self.ignored_columns_ids
382
- )
342
+ result['is_fake'] = not column_id or column_id in self.ignored_columns_ids
383
343
  if full_accessor_name in self._report_columns_by_name:
384
- result['visible'] = (
385
- self._report_columns_by_name[full_accessor_name].visible
386
- )
344
+ result['visible'] = self._report_columns_by_name[full_accessor_name].visible
387
345
  result['visible_title'] = 'Да' if result['visible'] else 'Нет'
388
346
 
389
347
  # "Количество"
@@ -429,16 +387,11 @@ class ReportInfo:
429
387
  """
430
388
  tree_manager = getattr(ReportFilterGroup, '_tree_manager')
431
389
  filter_groups_query = tree_manager.get_queryset_descendants(
432
- self.report_template.filter_groups.exclude(
433
- filters__column_id__in=self.ignored_columns_ids
434
- ),
435
- include_self=True
390
+ self.report_template.filter_groups.exclude(filters__column_id__in=self.ignored_columns_ids),
391
+ include_self=True,
436
392
  ).prefetch_related('filters')
437
393
 
438
- return OrderedDict(
439
- (filter_group.pk, filter_group)
440
- for filter_group in filter_groups_query
441
- )
394
+ return OrderedDict((filter_group.pk, filter_group) for filter_group in filter_groups_query)
442
395
 
443
396
  def _get_filter_data(self, report_filter):
444
397
  """Возвращает параметры фильтра.
@@ -448,13 +401,13 @@ class ReportInfo:
448
401
  column = self._report_columns_by_id[report_filter.column_id]
449
402
 
450
403
  return dict(
451
- column=column.name,
452
- index=report_filter.index,
453
- operator=report_filter.operator,
454
- exclude=report_filter.exclude,
455
- case_sensitive=report_filter.case_sensitive,
456
- values=report_filter.values or [],
457
- comment=report_filter.comment,
404
+ column=column.name,
405
+ index=report_filter.index,
406
+ operator=report_filter.operator,
407
+ exclude=report_filter.exclude,
408
+ case_sensitive=report_filter.case_sensitive,
409
+ values=report_filter.values or [],
410
+ comment=report_filter.comment,
458
411
  )
459
412
 
460
413
  def _get_filter_group_data(self, filter_group):
@@ -463,18 +416,12 @@ class ReportInfo:
463
416
  :rtype: dict
464
417
  """
465
418
  nested_groups = (
466
- nested_group
467
- for nested_group in self._filter_groups.values()
468
- if nested_group.parent_id == filter_group.pk
419
+ nested_group for nested_group in self._filter_groups.values() if nested_group.parent_id == filter_group.pk
469
420
  )
470
421
 
471
422
  return {
472
423
  self._OPERATOR_MAP[filter_group.operator]: tuple(
473
- (
474
- self._get_filter_group_data(obj)
475
- if isinstance(obj, ReportFilterGroup) else
476
- self._get_filter_data(obj)
477
- )
424
+ (self._get_filter_group_data(obj) if isinstance(obj, ReportFilterGroup) else self._get_filter_data(obj))
478
425
  for obj in chain(nested_groups, filter_group.filters.all())
479
426
  )
480
427
  }
@@ -546,11 +493,9 @@ class ReportInfo:
546
493
  :rtype: tuple
547
494
  """
548
495
  result = tuple(
549
- ReportSorting.objects.filter(
550
- column__report_template=self.report_template
551
- ).exclude(
552
- column_id__in=self.ignored_columns_ids
553
- ).order_by('index')
496
+ ReportSorting.objects.filter(column__report_template=self.report_template)
497
+ .exclude(column_id__in=self.ignored_columns_ids)
498
+ .order_by('index')
554
499
  )
555
500
 
556
501
  for sorting_params in result:
@@ -571,17 +516,13 @@ class ReportInfo:
571
516
 
572
517
  def get_sorting_data(self):
573
518
  """Возвращает параметры сортировки."""
574
- return tuple(
575
- self._get_sorting_data(sorting_params)
576
- for sorting_params in self._sorting_params_by_column_name
577
- )
519
+ return tuple(self._get_sorting_data(sorting_params) for sorting_params in self._sorting_params_by_column_name)
578
520
 
579
521
 
580
522
  class ReportTemplateWriter:
581
523
  """Класс, сохраняющий в БД данные шаблона отчета."""
582
524
 
583
- def __init__(self, report_template, columns_data, filters_data,
584
- sorting_data):
525
+ def __init__(self, report_template, columns_data, filters_data, sorting_data):
585
526
  """Инициализация экземпляра класса.
586
527
 
587
528
  :param report_template: Шаблон отчета
@@ -619,10 +560,7 @@ class ReportTemplateWriter:
619
560
  :rtype: bool
620
561
  """
621
562
  if report_template.data_source_name not in registry:
622
- self.errors.append(
623
- 'Источник данных "{}" не существует.'
624
- .format(report_template.data_source_name)
625
- )
563
+ self.errors.append('Источник данных "{}" не существует.'.format(report_template.data_source_name))
626
564
 
627
565
  return not self.errors
628
566
 
@@ -639,9 +577,7 @@ class ReportTemplateWriter:
639
577
  # ---------------------------------------------------------------------
640
578
  # Проверка наличия в источнике данных указанных столбцов.
641
579
 
642
- data_source = registry.get(
643
- self._report_template.data_source_name
644
- ).get_data_source_descriptor()
580
+ data_source = registry.get(self._report_template.data_source_name).get_data_source_descriptor()
645
581
 
646
582
  for column_params in columns_data:
647
583
  if 'accessor_name' not in column_params:
@@ -650,29 +586,18 @@ class ReportTemplateWriter:
650
586
 
651
587
  full_accessor_name = column_params['accessor_name']
652
588
  if full_accessor_name in self._column_descriptors:
653
- self.errors.append(
654
- 'Колонка {} указана более одного раза.'
655
- .format(full_accessor_name)
656
- )
589
+ self.errors.append('Колонка {} указана более одного раза.'.format(full_accessor_name))
657
590
  else:
658
591
  try:
659
- column_descriptor = data_source.get_column_descriptor(
660
- full_accessor_name
661
- )
592
+ column_descriptor = data_source.get_column_descriptor(full_accessor_name)
662
593
  except FieldDoesNotExist:
663
594
  self.errors.append(
664
- 'Колонки "{}" нет в источнике данных "{}".'
665
- .format(full_accessor_name, data_source.title)
595
+ 'Колонки "{}" нет в источнике данных "{}".'.format(full_accessor_name, data_source.title)
666
596
  )
667
597
  else:
668
- self._column_descriptors[full_accessor_name] = (
669
- column_descriptor
670
- )
598
+ self._column_descriptors[full_accessor_name] = column_descriptor
671
599
 
672
- if not any(
673
- column_params.get('visible', False)
674
- for column_params in columns_data
675
- ):
600
+ if not any(column_params.get('visible', False) for column_params in columns_data):
676
601
  self.errors.append('В отчете нет ни одного видимого столбца.')
677
602
  # ---------------------------------------------------------------------
678
603
 
@@ -695,12 +620,8 @@ class ReportTemplateWriter:
695
620
  return False
696
621
 
697
622
  # Проверка вложенной группы фильтров.
698
- if (
699
- 'AND' in filter_params and
700
- not self._is_filters_data_valid(filter_params['AND'])
701
- ) or (
702
- 'OR' in filter_params and
703
- not self._is_filters_data_valid(filter_params['OR'])
623
+ if ('AND' in filter_params and not self._is_filters_data_valid(filter_params['AND'])) or (
624
+ 'OR' in filter_params and not self._is_filters_data_valid(filter_params['OR'])
704
625
  ):
705
626
  return False
706
627
 
@@ -711,12 +632,9 @@ class ReportTemplateWriter:
711
632
  'values',
712
633
  )
713
634
  if (
714
- 'AND' not in filter_params and
715
- 'OR' not in filter_params and
716
- any(
717
- param_name not in filter_params
718
- for param_name in param_names
719
- )
635
+ 'AND' not in filter_params
636
+ and 'OR' not in filter_params
637
+ and any(param_name not in filter_params for param_name in param_names)
720
638
  ):
721
639
  return False
722
640
 
@@ -736,10 +654,7 @@ class ReportTemplateWriter:
736
654
  'column',
737
655
  'direction',
738
656
  )
739
- if any(
740
- param_name not in sorting_params
741
- for param_name in param_names
742
- ):
657
+ if any(param_name not in sorting_params for param_name in param_names):
743
658
  return False
744
659
 
745
660
  return True
@@ -751,21 +666,13 @@ class ReportTemplateWriter:
751
666
  найдены ошибки.
752
667
  """
753
668
  if not self._is_report_template_valid(self._report_template):
754
- raise ValidationError(
755
- 'Параметры шаблона указаны некорректно.'
756
- )
669
+ raise ValidationError('Параметры шаблона указаны некорректно.')
757
670
  if not self._is_columns_data_valid(self._columns_data):
758
- raise ValidationError(
759
- 'Параметры столбцов указаны некорректно.'
760
- )
671
+ raise ValidationError('Параметры столбцов указаны некорректно.')
761
672
  if not self._is_filters_data_valid(self._filters_data):
762
- raise ValidationError(
763
- 'Параметры фильтров указаны некорректно.'
764
- )
673
+ raise ValidationError('Параметры фильтров указаны некорректно.')
765
674
  if not self._is_sorting_data_valid(self._sorting_data):
766
- raise ValidationError(
767
- 'Параметры сортировки указаны некорректно.'
768
- )
675
+ raise ValidationError('Параметры сортировки указаны некорректно.')
769
676
 
770
677
  def _write_template(self):
771
678
  """Сохранение в БД шаблона отчета."""
@@ -774,20 +681,13 @@ class ReportTemplateWriter:
774
681
  def _write_columns(self):
775
682
  """Сохранение в БД столбцов."""
776
683
  column_descriptor_names = set(
777
- column_descriptor.full_accessor_name
778
- for column_descriptor in self._column_descriptors.values()
684
+ column_descriptor.full_accessor_name for column_descriptor in self._column_descriptors.values()
779
685
  )
780
686
 
781
687
  columns_query = self._report_template.columns.order_by('index')
782
- report_columns = OrderedDict(
783
- (report_column.name, report_column)
784
- for report_column in columns_query
785
- )
688
+ report_columns = OrderedDict((report_column.name, report_column) for report_column in columns_query)
786
689
 
787
- columns_data = {
788
- column_data['accessor_name']: column_data
789
- for column_data in self._columns_data
790
- }
690
+ columns_data = {column_data['accessor_name']: column_data for column_data in self._columns_data}
791
691
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
792
692
  # Сначала нужно удалить столбцы, которых нет в запросе.
793
693
 
@@ -797,12 +697,8 @@ class ReportTemplateWriter:
797
697
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
798
698
 
799
699
  created_report_columns = []
800
- for index, column_descriptor in enumerate(
801
- self._column_descriptors.values(), 1
802
- ):
803
- report_column = report_columns.get(
804
- column_descriptor.full_accessor_name
805
- )
700
+ for index, column_descriptor in enumerate(self._column_descriptors.values(), 1):
701
+ report_column = report_columns.get(column_descriptor.full_accessor_name)
806
702
 
807
703
  column_data = columns_data[column_descriptor.full_accessor_name]
808
704
  visible = column_data.get('visible', False)
@@ -818,17 +714,17 @@ class ReportTemplateWriter:
818
714
  title=column_descriptor.title,
819
715
  visible=visible,
820
716
  by_value=by_value,
821
- total=total
717
+ total=total,
822
718
  )
823
719
  )
824
720
 
825
721
  elif (
826
- report_column.name != column_descriptor.full_accessor_name or
827
- report_column.index != index or
828
- report_column.title != column_descriptor.title or
829
- report_column.visible != visible or
830
- report_column.by_value != by_value or
831
- report_column.total != total
722
+ report_column.name != column_descriptor.full_accessor_name
723
+ or report_column.index != index
724
+ or report_column.title != column_descriptor.title
725
+ or report_column.visible != visible
726
+ or report_column.by_value != by_value
727
+ or report_column.total != total
832
728
  ):
833
729
  report_column.name = column_descriptor.full_accessor_name
834
730
  report_column.index = index
@@ -841,8 +737,7 @@ class ReportTemplateWriter:
841
737
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
842
738
  # Сохранение столбцов для дальнейшего использования.
843
739
 
844
- for report_column in chain(report_columns.values(),
845
- created_report_columns):
740
+ for report_column in chain(report_columns.values(), created_report_columns):
846
741
  self._report_columns[report_column.name] = report_column
847
742
  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
848
743
 
@@ -963,26 +858,26 @@ class Pack(PackValidationMixin, ObjectPack):
963
858
  add_window = edit_window = EditWindow
964
859
 
965
860
  def __init__(self):
966
- super(Pack, self).__init__()
967
- # ---------------------------------------------------------------------
861
+ super().__init__()
862
+
968
863
  self.columns_action = ColumnsAction()
969
864
  self.build_action = BuildAction()
970
865
 
971
- self.actions.extend((
972
- self.columns_action,
973
- self.build_action,
974
- ))
975
- # ---------------------------------------------------------------------
866
+ self.actions.extend(
867
+ (
868
+ self.columns_action,
869
+ self.build_action,
870
+ )
871
+ )
976
872
 
977
873
  def prepare_row(self, obj, request, context):
978
- obj = super(Pack, self).prepare_row(
979
- obj, request, context
980
- )
874
+ obj = super().prepare_row(obj, request, context)
875
+
981
876
  obj.valid = not (ReportInfo(obj).ignored_columns_ids)
982
877
  return obj
983
878
 
984
879
  def declare_context(self, action):
985
- result = super(Pack, self).declare_context(action)
880
+ result = super().declare_context(action)
986
881
 
987
882
  if action is self.save_action:
988
883
  result.update(
@@ -996,24 +891,18 @@ class Pack(PackValidationMixin, ObjectPack):
996
891
  return result
997
892
 
998
893
  def get_list_window_params(self, params, request, context):
999
- result = super(Pack, self).get_list_window_params(
1000
- params, request, context
1001
- )
894
+ result = super().get_list_window_params(params, request, context)
1002
895
 
1003
896
  result['build_action_url'] = self.build_action.get_absolute_url()
1004
897
 
1005
898
  return result
1006
899
 
1007
900
  def get_edit_window_params(self, params, request, context):
1008
- result = super(Pack, self).get_edit_window_params(
1009
- params, request, context
1010
- )
901
+ result = super().get_edit_window_params(params, request, context)
1011
902
 
1012
903
  result['maximized'] = True
1013
904
 
1014
- result['available_columns_action_url'] = (
1015
- self.columns_action.get_absolute_url()
1016
- )
905
+ result['available_columns_action_url'] = self.columns_action.get_absolute_url()
1017
906
 
1018
907
  # pylint: disable=dict-iter-method
1019
908
  result['data_sources_params'] = registry.iteritems()
@@ -1044,10 +933,7 @@ class Pack(PackValidationMixin, ObjectPack):
1044
933
  try:
1045
934
  writer.validate()
1046
935
  except ValidationError as error:
1047
- raise ValidationError('\n'.join((
1048
- str(error),
1049
- '\n'.join(writer.errors)
1050
- )))
936
+ raise ValidationError('\n'.join((str(error), '\n'.join(writer.errors))))
1051
937
 
1052
938
  writer.write()
1053
939
 
@@ -1073,7 +959,7 @@ class Pack(PackValidationMixin, ObjectPack):
1073
959
  ).iterator():
1074
960
  report_column.safe_delete()
1075
961
 
1076
- super(Pack, self).delete_row(obj_id, request, context)
962
+ super().delete_row(obj_id, request, context)
1077
963
 
1078
964
  def extend_menu(self, menu):
1079
965
  return menu.SubMenu(
@@ -1081,5 +967,5 @@ class Pack(PackValidationMixin, ObjectPack):
1081
967
  menu.SubMenu(
1082
968
  'Конструктор отчетов',
1083
969
  menu.Item('Редактор шаблонов', self.list_window_action),
1084
- )
970
+ ),
1085
971
  )