educommon 3.13.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 (220) 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 +4 -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.0.dist-info → educommon-3.13.2.dist-info}/METADATA +26 -14
  214. educommon-3.13.2.dist-info/RECORD +354 -0
  215. educommon/utils/patches.py +0 -27
  216. educommon/version.conf +0 -11
  217. educommon-3.13.0.dist-info/RECORD +0 -357
  218. educommon-3.13.0.dist-info/dependency_links.txt +0 -1
  219. {educommon-3.13.0.dist-info → educommon-3.13.2.dist-info}/WHEEL +0 -0
  220. {educommon-3.13.0.dist-info → educommon-3.13.2.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
1
1
  """Расширение поведения интерфейсов."""
2
+
2
3
  from m3_ext.ui import (
3
4
  all_components as ext,
4
5
  )
@@ -9,8 +10,7 @@ from objectpack.ui import (
9
10
 
10
11
 
11
12
  class BaseEditWinExtender:
12
- """
13
- Базовый объект для расширения окон редактирования.
13
+ """Базовый объект для расширения окон редактирования.
14
14
 
15
15
  ``_extend_edit_win`` - добавление и размещение контролов
16
16
  ``bind_to_object`` - заполнение объекта данными из полей формы
@@ -31,39 +31,31 @@ class BaseEditWinExtender:
31
31
  self._extend_edit_win()
32
32
 
33
33
  def _extend_edit_win(self):
34
- """
35
- Расширение формы окна.
34
+ """Расширение формы окна.
36
35
 
37
36
  ..code::
38
37
 
39
38
  for fld in self.model_fields_to_controls(self.model_fields):
40
39
  self._win.form.items.append(fld)
41
-
42
40
  """
43
41
  raise NotImplementedError()
44
42
 
45
43
  def model_fields_to_controls(self, fields):
46
44
  """Шорткат для генерации контролов."""
47
45
  assert self.model, 'No model defined in Extender!'
48
- return model_fields_to_controls(
49
- self.model,
50
- self._win,
51
- field_list=fields,
52
- model_register=self.model_register
53
- )
46
+ return model_fields_to_controls(self.model, self._win, field_list=fields, model_register=self.model_register)
54
47
 
55
48
  # -------------------------------------------------------------------------
56
49
  # Биндинг из формы в объект
57
50
 
58
51
  @classmethod
59
52
  def set_value(cls, instance, field_names, value):
60
- """
61
- Установка значения поля (полей).
53
+ """Установка значения поля (полей).
62
54
 
63
55
  :param instance: инстанс модели, которая расширяет основную ``model``
64
56
  :param list field_names: список связаных полей (либо одно поле)
65
57
  :raise: DoesNotExist если предварительно не инстанцировали зависимые
66
- сущности (для случая связанных полей)
58
+ сущности (для случая связанных полей).
67
59
  """
68
60
  if len(field_names) == 1:
69
61
  # связанных полей нет
@@ -76,15 +68,13 @@ class BaseEditWinExtender:
76
68
 
77
69
  @classmethod
78
70
  def bind_to_object(cls, instance, context):
79
- """
80
- Заполнение полей ``model_fields`` модели instance по полям формы.
71
+ """Заполнение полей ``model_fields`` модели instance по полям формы.
81
72
 
82
73
  :param instance: инстанс модели, которая расширяет основную ``model``
83
74
  :param context: контекст
84
75
  :type context: m3.actions.context.DeclarativeActionContext
85
76
  """
86
- assert cls.model_fields is not None, (
87
- 'No model_fields defined in Extender')
77
+ assert cls.model_fields is not None, 'No model_fields defined in Extender'
88
78
 
89
79
  for field_name in cls.model_fields:
90
80
  try:
@@ -99,13 +89,11 @@ class BaseEditWinExtender:
99
89
  # Биндинг из объекта в форму
100
90
 
101
91
  def bind_from_object(self, instance):
102
- """
103
- Заполнение полей ``model_fields`` формы по полям модели instance.
92
+ """Заполнение полей ``model_fields`` формы по полям модели instance.
104
93
 
105
94
  :param instance: инстанс модели, которая расширяет основную ``model``
106
95
  """
107
- assert self.model_fields is not None, (
108
- 'No model_fields defined in Extender')
96
+ assert self.model_fields is not None, 'No model_fields defined in Extender'
109
97
  for name in self.model_fields:
110
98
  field = self._win.find_by_name(name)
111
99
  field_names = field.name.split('.')
@@ -114,8 +102,7 @@ class BaseEditWinExtender:
114
102
  self._set_value_to_field(field, value)
115
103
 
116
104
  def _get_value(self, instance, field_names):
117
- """
118
- Получение значение поля (полей).
105
+ """Получение значение поля (полей).
119
106
 
120
107
  :param instance: инстанс модели, которая расширяет основную ``model``
121
108
  :param list field_names: список связаных полей (либо одно поле)
@@ -132,8 +119,7 @@ class BaseEditWinExtender:
132
119
 
133
120
  @staticmethod
134
121
  def _set_value_to_field(field, value):
135
- """
136
- Установка значения в поле.
122
+ """Установка значения в поле.
137
123
 
138
124
  :param field: наследник BaseExtField
139
125
  :param value: значение для установки в поле
@@ -145,22 +131,18 @@ class BaseEditWinExtender:
145
131
  if isinstance(field, ext.ExtMultiSelectField):
146
132
  field.value = pack.model.get_serialized_values(value)
147
133
  else:
148
- field.default_text = pack.get_display_text(
149
- value, field.display_field)
134
+ field.default_text = pack.get_display_text(value, field.display_field)
150
135
  elif isinstance(field, ext.ExtCheckBox):
151
136
  field.checked = bool(value)
152
137
 
153
138
  def set_params(self, params):
154
- """
155
- Установка параметров компонентам.
139
+ """Установка параметров компонентам.
156
140
 
157
141
  Выполняется по завершению создания компонент, размещению на форме и
158
142
  после биндинга значений в форму.
159
143
 
160
144
  ..code::
161
145
 
162
- self._win.field__some.make_read_only(
163
- access_off=params['instance'].date > datetime.date.today()
164
- )
146
+ self._win.field__some.make_read_only(access_off=params['instance'].date > datetime.date.today())
165
147
  """
166
148
  pass
@@ -29,6 +29,7 @@ with TransactionCM('user_import'):
29
29
  user.set_password(pwd)
30
30
  user.save()
31
31
  """
32
+
32
33
  from functools import (
33
34
  wraps,
34
35
  )
@@ -58,27 +59,25 @@ def _prepare_state():
58
59
  if not hasattr(_state, 'situation'):
59
60
  _reset_state()
60
61
 
62
+
61
63
  _reset_state()
62
64
 
63
65
 
64
66
  class AbortTransaction(Exception):
65
- """
66
- Исключение, прерывающее текущий CM (SavePointCM/TransactionCM).
67
+ """Исключение, прерывающее текущий CM (SavePointCM/TransactionCM).
68
+
67
69
  Поймав это исключение CM откатывает изменения,
68
70
  произошедшие с момента входа в него и корректно завершается.
69
71
  """
72
+
70
73
  pass
71
74
 
72
75
 
73
76
  class SavePointCM:
74
- """
75
- Context Manager создающий на время своего действия savepoint
76
- """
77
+ """Context Manager создающий на время своего действия savepoint."""
77
78
 
78
79
  def __init__(self):
79
- assert _state.situation, (
80
- 'Must be nested in TransactionCM!'
81
- )
80
+ assert _state.situation, 'Must be nested in TransactionCM!'
82
81
  cookie = uuid4()
83
82
  _state.cookies.append(cookie)
84
83
  self._cookie = cookie
@@ -103,15 +102,11 @@ class SavePointCM:
103
102
 
104
103
 
105
104
  class TransactionCM:
106
- """
107
- ContextManager создающий "ручную" транзакцию
108
- """
105
+ """ContextManager создающий "ручную" транзакцию."""
109
106
 
110
107
  def __init__(self, situation, rollback_all=True, using=None):
111
108
  _prepare_state()
112
- assert not _state.situation, (
113
- 'Nested contexts not supported!'
114
- )
109
+ assert not _state.situation, 'Nested contexts not supported!'
115
110
  _reset_state()
116
111
  _state.situation = self._situation = situation
117
112
 
@@ -126,10 +121,10 @@ class TransactionCM:
126
121
  try:
127
122
  if ex_type is None:
128
123
  try:
129
- for (task, cookie) in _state.task_queue:
124
+ for task, cookie in _state.task_queue:
130
125
  if cookie not in _state.rolled_back:
131
126
  task()
132
- except Exception as e:
127
+ except Exception:
133
128
  transaction.rollback(self._using)
134
129
  _reset_state()
135
130
  raise
@@ -149,22 +144,25 @@ class TransactionCM:
149
144
 
150
145
 
151
146
  def delay_in_situations(*situations):
152
- """
153
- Оборачивает функцию и возвращает функцию-обработчик сигнала Django.
147
+ """Оборачивает функцию и возвращает функцию-обработчик сигнала Django.
148
+
154
149
  В контексте одной из ситуаций, перечисленных в @situations
155
150
  выполнение функции, возвращённой оборачиваемой функцией,
156
151
  будет отложено до успешного завершения TransactionCM, создавшего ситуацию.
157
152
  """
153
+
158
154
  def wrapper(fn):
159
155
  @wraps(fn)
160
156
  def inner(*args, **kwargs):
161
157
  cont = fn(*args, **kwargs)
162
- assert callable(cont), "Task must return the callable object!"
158
+ assert callable(cont), 'Task must return the callable object!'
163
159
  situation = getattr(_state, 'situation', None)
164
160
  if not situation or situation not in situations:
165
161
  cont()
166
162
  else:
167
163
  cookie = (_state.cookies or [None])[-1]
168
164
  _state.task_queue.append((cont, cookie))
165
+
169
166
  return inner
167
+
170
168
  return wrapper
@@ -60,12 +60,11 @@ class BaseGridPack(BasePack):
60
60
 
61
61
  @property
62
62
  def id_param_name(self):
63
- return '%s_id' % self.short_name
63
+ return f'{self.short_name}_id'
64
64
 
65
65
  @property
66
66
  def grid_panel(cls):
67
- """
68
- Класс панели с гридом.
67
+ """Класс панели с гридом.
69
68
 
70
69
  .. note::
71
70
  Вынесено в метод для случая, когда пак работает с гридом,
@@ -74,14 +73,14 @@ class BaseGridPack(BasePack):
74
73
  return cls.window.grid_panel_cls
75
74
 
76
75
  def __init__(self):
77
- super(BaseGridPack, self).__init__()
76
+ super().__init__()
77
+
78
78
  self.grid_action = BaseGridCreateAction()
79
79
  self.window_action = BaseGridWinAction()
80
80
  self.actions.extend([self.grid_action, self.window_action])
81
81
 
82
82
  def create_columns(self, request, context):
83
- """
84
- Метод возвращающий колонки.
83
+ """Метод возвращающий колонки.
85
84
 
86
85
  .. seealso:: objectpack.actions.ObjectPack.columns
87
86
 
@@ -90,18 +89,17 @@ class BaseGridPack(BasePack):
90
89
  return []
91
90
 
92
91
  def create_grid(self, columns):
93
- """
94
- Создание грида.
92
+ """Создание грида.
95
93
 
96
94
  :param list columns: список колонок
97
95
  :rtype: m3_ext.ui.ExtObjectGrid
98
96
  """
99
97
  grid = self.grid_panel.create_grid(pack=self, columns=columns)
98
+
100
99
  return grid
101
100
 
102
101
  def set_grid_params(self, grid, request, context):
103
- """
104
- Настройка параметров для конфигурации грида.
102
+ """Настройка параметров для конфигурации грида.
105
103
 
106
104
  Параметры грида передаются панели с гридом в метод configure_grid.
107
105
  :param grid: грид
@@ -115,11 +113,12 @@ class BaseGridPack(BasePack):
115
113
  """
116
114
  # пак для настройки грида (column_param_name, id_param_name, url_data)
117
115
  params = {'pack': self}
116
+
118
117
  return params
119
118
 
120
119
  def configure_grid(self, grid, request, context):
121
- """
122
- Метод конфигурирования грида после его создания.
120
+ """Метод конфигурирования грида после его создания.
121
+
123
122
  :param grid: грид
124
123
  :type grid: m3_ext.ui.ExtObjectGrid
125
124
  :param request: Запрос
@@ -129,34 +128,31 @@ class BaseGridPack(BasePack):
129
128
  """
130
129
  params = self.set_grid_params(grid, request, context)
131
130
  grid = self.grid_panel.configure_grid(grid, params)
131
+
132
132
  return grid
133
133
 
134
134
  def get_grid_action_url(self):
135
- """
136
- Получение адреса экшна построения грид.
135
+ """Получение адреса экшна построения грид.
137
136
 
138
137
  :rtype: str
139
138
  """
140
139
  return self.grid_action.get_absolute_url()
141
140
 
142
141
  def get_rows_url(self):
143
- """
144
- Получение адреса экшна, возвращающего строки грида.
142
+ """Получение адреса экшна, возвращающего строки грида.
145
143
 
146
144
  Должен быть определен в потомке.
147
145
  :rtype: str
148
146
  """
149
- raise NotImplementedError(
150
- "Не определен метод get_rows_url() "
151
- "в %s!" % self.__class__.__name__)
147
+ raise NotImplementedError(f'Не определен метод get_rows_url() в {self.__class__.__name__}!')
152
148
 
153
149
  def create_window(self, request, context):
154
150
  """Получение окна."""
155
151
  return self.window()
156
152
 
157
153
  def get_window_params(self, request, context):
158
- """
159
- Параметры для показа окна
154
+ """Параметры для показа окна.
155
+
160
156
  :param request: Запрос
161
157
  :type request: django.http.HttpRequest
162
158
  :param context: Контекст
@@ -170,8 +166,9 @@ class BaseGridPack(BasePack):
170
166
  """
171
167
  params = {
172
168
  # пак отвечающий за получения грида окном
173
- "grid_pack": self
169
+ 'grid_pack': self
174
170
  }
171
+
175
172
  return params
176
173
 
177
174
 
@@ -185,6 +182,7 @@ class BaseGridCreateAction(BaseAction):
185
182
  columns = pack.create_columns(request, context)
186
183
  grid = pack.create_grid(columns)
187
184
  pack.configure_grid(grid, request, context)
185
+
188
186
  return ExtUIComponentResult(grid)
189
187
 
190
188
 
@@ -197,15 +195,14 @@ class BaseGridWinAction(BaseWindowAction):
197
195
  self.win = self.parent.create_window(self.request, self.context)
198
196
 
199
197
  def set_window_params(self):
200
- super(BaseGridWinAction, self).set_window_params()
201
- self.win_params = self.parent.get_window_params(
202
- self.request, self.context)
198
+ super().set_window_params()
199
+
200
+ self.win_params = self.parent.get_window_params(self.request, self.context)
203
201
 
204
202
 
205
203
  class ExtObjectRowsAction(ObjectRowsAction):
206
204
  def get_total_count(self):
207
- """
208
- В отличие от оригинала убирает из запроса лишнюю обработку даных.
205
+ """В отличие от оригинала убирает из запроса лишнюю обработку данных.
209
206
 
210
207
  :return: Количество объектов в выборке
211
208
  :rtype: int
@@ -214,10 +211,10 @@ class ExtObjectRowsAction(ObjectRowsAction):
214
211
 
215
212
 
216
213
  class RelationsCheckMixin:
217
- """
218
- Миксин для экшенов удаления и редактирования, проверяющий наличие
219
- ссылок на редактируемый/удаляемый объект и выводящий данную информацию
220
- в табличном виде.
214
+ """Миксин для экшенов удаления и редактирования.
215
+
216
+ Проверяет наличие ссылок на редактируемый/удаляемый объект
217
+ и выводящий данную информацию в табличном виде.
221
218
  """
222
219
 
223
220
  # Описание настроек отображения информации для каждой модели.
@@ -229,8 +226,7 @@ class RelationsCheckMixin:
229
226
  err_msg = 'На объект "{obj}" есть ссылки:'
230
227
  render_template_name = 'relations-check-mixin-template.html'
231
228
 
232
- def __init__(self, rel_conf=None, rel_list=None,
233
- rel_ignore_list=None, err_msg=None, *args, **kwargs):
229
+ def __init__(self, rel_conf=None, rel_list=None, rel_ignore_list=None, err_msg=None, *args, **kwargs):
234
230
  """
235
231
  :param rel_conf: настройки отображения
236
232
  :type dict
@@ -265,28 +261,21 @@ class RelationsCheckMixin:
265
261
  self.rel_ignore_list = rel_ignore_list
266
262
  if err_msg:
267
263
  self.err_msg = err_msg
268
- super(RelationsCheckMixin, self).__init__(*args, **kwargs)
264
+
265
+ super().__init__(*args, **kwargs)
269
266
 
270
267
  def _get_relations_to_check(self):
271
268
  """Получение всех связанных моделей для проверки."""
272
269
  model = self._get_check_model()
273
270
  opts = ModelOptions(model)
274
- all_related_objects = [
275
- rel_obj.relation for rel_obj in opts.get_all_related_objects()
276
- ]
271
+ all_related_objects = [rel_obj.relation for rel_obj in opts.get_all_related_objects()]
277
272
  result = all_related_objects[:]
278
273
 
279
274
  if self.rel_ignore_list:
280
- result = [
281
- rel for rel in all_related_objects
282
- if rel.field.model.__name__ not in self.rel_ignore_list
283
- ]
275
+ result = [rel for rel in all_related_objects if rel.field.model.__name__ not in self.rel_ignore_list]
284
276
 
285
277
  if self.rel_list:
286
- result = [
287
- rel for rel in all_related_objects
288
- if rel.field.model.__name__ in self.rel_list
289
- ]
278
+ result = [rel for rel in all_related_objects if rel.field.model.__name__ in self.rel_list]
290
279
 
291
280
  return result
292
281
 
@@ -295,11 +284,10 @@ class RelationsCheckMixin:
295
284
 
296
285
  def _extract_proxy_from_model(model):
297
286
  """Если получена не модель, а прокси, то извлекает из него модель.
287
+
298
288
  Функция рекурсивна, т.к. возможны прокси на прокси.
299
289
  """
300
- if issubclass(model, ModelProxy) and hasattr(
301
- model, 'model'
302
- ):
290
+ if issubclass(model, ModelProxy) and hasattr(model, 'model'):
303
291
  model = _extract_proxy_from_model(model.model)
304
292
  elif model._meta.proxy:
305
293
  # прокси django
@@ -314,11 +302,12 @@ class RelationsCheckMixin:
314
302
  ids = getattr(context, self.parent.id_param_name, [])
315
303
  if isinstance(ids, int):
316
304
  ids = [ids]
305
+
317
306
  return self._get_check_model().objects.filter(id__in=ids)
318
307
 
319
308
  def collect_related_objects(self, request, context):
320
- """
321
- Получение списка связанных объектов
309
+ """Получение списка связанных объектов.
310
+
322
311
  :param request: Запрос
323
312
  :type request: django.http.HttpRequest
324
313
  :param context: Контекст
@@ -336,26 +325,25 @@ class RelationsCheckMixin:
336
325
  for obj in objects:
337
326
  assert isinstance(obj, model)
338
327
 
339
- object_relations = result.setdefault(obj.id, {
340
- 'object': obj,
341
- 'relations': [],
342
- 'err_msg': self.err_msg.format(
343
- model_verbose=model._meta.verbose_name.capitalize(),
344
- obj=obj,
345
- ),
346
- })
328
+ object_relations = result.setdefault(
329
+ obj.id,
330
+ {
331
+ 'object': obj,
332
+ 'relations': [],
333
+ 'err_msg': self.err_msg.format(
334
+ model_verbose=model._meta.verbose_name.capitalize(),
335
+ obj=obj,
336
+ ),
337
+ },
338
+ )
347
339
 
348
340
  for rel in relations:
349
- assert getattr(
350
- rel, 'parent_model', getattr(rel, 'model')
351
- ) == model
341
+ assert getattr(rel, 'parent_model', getattr(rel, 'model')) == model
352
342
 
353
343
  rel_model_name = rel.field.model.__name__
354
344
  conf = self.rel_conf.get(rel_model_name, {})
355
345
 
356
- query = rel.field.model.objects.filter(
357
- **{str(rel.field.attname): obj.pk}
358
- )
346
+ query = rel.field.model.objects.filter(**{str(rel.field.attname): obj.pk})
359
347
  if conf.get('get_query'):
360
348
  query = conf['get_query'](query, obj)
361
349
 
@@ -367,14 +355,15 @@ class RelationsCheckMixin:
367
355
  objects = [display(o) for o in query]
368
356
 
369
357
  if count:
370
- object_relations['relations'].append({
371
- 'model': rel.field.model,
372
- 'title': (conf.get('title') or
373
- rel.field.model._meta.verbose_name),
374
- 'columns': conf.get('columns'),
375
- 'objects': objects,
376
- 'count': count,
377
- })
358
+ object_relations['relations'].append(
359
+ {
360
+ 'model': rel.field.model,
361
+ 'title': (conf.get('title') or rel.field.model._meta.verbose_name),
362
+ 'columns': conf.get('columns'),
363
+ 'objects': objects,
364
+ 'count': count,
365
+ }
366
+ )
378
367
 
379
368
  return dict(
380
369
  items=[v for v in result.values() if v['relations']],
@@ -382,8 +371,8 @@ class RelationsCheckMixin:
382
371
  )
383
372
 
384
373
  def pre_run(self, request, context):
385
- """
386
- Вывод окна отчета
374
+ """Вывод окна отчета.
375
+
387
376
  :param request: Запрос
388
377
  :type request: django.http.HttpRequest
389
378
  :param context: Контекст
@@ -391,13 +380,11 @@ class RelationsCheckMixin:
391
380
 
392
381
  """
393
382
 
394
- super(RelationsCheckMixin, self).pre_run(request, context)
383
+ super().pre_run(request, context)
395
384
 
396
- related_objects_data = self.collect_related_objects(
397
- request, context)
385
+ related_objects_data = self.collect_related_objects(request, context)
398
386
 
399
387
  if related_objects_data['items']:
400
-
401
388
  html = render_to_string(
402
389
  self.render_template_name,
403
390
  related_objects_data,
@@ -406,10 +393,7 @@ class RelationsCheckMixin:
406
393
  win = ui.RelatedErrorWindow()
407
394
  win.set_params(params)
408
395
 
409
- return OperationResult(
410
- success=False,
411
- code=win.get_script()
412
- )
396
+ return OperationResult(success=False, code=win.get_script())
413
397
 
414
398
 
415
399
  class ViewWindowPackMixin:
@@ -419,16 +403,14 @@ class ViewWindowPackMixin:
419
403
  """
420
404
 
421
405
  def create_edit_window(self, create_new, request, context):
422
- window = super(ViewWindowPackMixin, self).create_edit_window(
423
- create_new, request, context
424
- )
406
+ window = super().create_edit_window(create_new, request, context)
407
+
425
408
  window.make_read_only()
409
+
426
410
  return window
427
411
 
428
412
  def create_list_window(self, is_select_mode, request, context):
429
- window = super(ViewWindowPackMixin, self).create_list_window(
430
- is_select_mode, request, context
431
- )
413
+ window = super().create_list_window(is_select_mode, request, context)
432
414
 
433
415
  reconfigure_grid_by_access(window.grid)
434
416
 
@@ -4,6 +4,11 @@ from django.apps import (
4
4
 
5
5
 
6
6
  class EduObjectPackConfig(AppConfig):
7
+ """Конфигурация приложения educommon.objectpack.
8
+
9
+ Определяет имя, метку и читаемое имя Django-приложения,
10
+ содержащего расширения и дополнения к objectpack.
11
+ """
7
12
 
8
13
  name = 'educommon.objectpack'
9
14
  label = 'educommon_objectpack'