flask-appbuilder 3.2.1rc1__py3-none-any.whl → 5.0.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 (228) hide show
  1. flask_appbuilder/__init__.py +2 -3
  2. flask_appbuilder/_compat.py +0 -1
  3. flask_appbuilder/actions.py +14 -14
  4. flask_appbuilder/api/__init__.py +741 -527
  5. flask_appbuilder/api/convert.py +104 -98
  6. flask_appbuilder/api/manager.py +14 -8
  7. flask_appbuilder/api/schemas.py +12 -1
  8. flask_appbuilder/babel/manager.py +12 -16
  9. flask_appbuilder/base.py +353 -280
  10. flask_appbuilder/basemanager.py +1 -1
  11. flask_appbuilder/baseviews.py +241 -164
  12. flask_appbuilder/charts/jsontools.py +10 -10
  13. flask_appbuilder/charts/views.py +56 -60
  14. flask_appbuilder/cli.py +115 -70
  15. flask_appbuilder/const.py +52 -52
  16. flask_appbuilder/exceptions.py +67 -5
  17. flask_appbuilder/fields.py +32 -23
  18. flask_appbuilder/fieldwidgets.py +34 -27
  19. flask_appbuilder/filemanager.py +33 -45
  20. flask_appbuilder/filters.py +11 -13
  21. flask_appbuilder/forms.py +31 -35
  22. flask_appbuilder/hooks.py +90 -0
  23. flask_appbuilder/menu.py +35 -10
  24. flask_appbuilder/models/base.py +47 -57
  25. flask_appbuilder/models/decorators.py +13 -13
  26. flask_appbuilder/models/filters.py +42 -38
  27. flask_appbuilder/models/generic/__init__.py +29 -29
  28. flask_appbuilder/models/generic/filters.py +11 -3
  29. flask_appbuilder/models/generic/interface.py +1 -3
  30. flask_appbuilder/models/group.py +37 -39
  31. flask_appbuilder/models/mixins.py +22 -18
  32. flask_appbuilder/models/sqla/__init__.py +19 -72
  33. flask_appbuilder/models/sqla/base.py +24 -0
  34. flask_appbuilder/models/sqla/base_legacy.py +132 -0
  35. flask_appbuilder/models/sqla/filters.py +132 -19
  36. flask_appbuilder/models/sqla/interface.py +390 -276
  37. flask_appbuilder/security/api.py +31 -35
  38. flask_appbuilder/security/decorators.py +181 -83
  39. flask_appbuilder/security/forms.py +20 -31
  40. flask_appbuilder/security/manager.py +715 -489
  41. flask_appbuilder/security/registerviews.py +29 -112
  42. flask_appbuilder/security/schemas.py +43 -0
  43. flask_appbuilder/security/sqla/apis/__init__.py +8 -0
  44. flask_appbuilder/security/sqla/apis/group/__init__.py +1 -0
  45. flask_appbuilder/security/sqla/apis/group/api.py +227 -0
  46. flask_appbuilder/security/sqla/apis/group/schema.py +73 -0
  47. flask_appbuilder/security/sqla/apis/permission/__init__.py +1 -0
  48. flask_appbuilder/security/sqla/apis/permission/api.py +19 -0
  49. flask_appbuilder/security/sqla/apis/permission_view_menu/__init__.py +1 -0
  50. flask_appbuilder/security/sqla/apis/permission_view_menu/api.py +16 -0
  51. flask_appbuilder/security/sqla/apis/role/__init__.py +1 -0
  52. flask_appbuilder/security/sqla/apis/role/api.py +306 -0
  53. flask_appbuilder/security/sqla/apis/role/schema.py +27 -0
  54. flask_appbuilder/security/sqla/apis/user/__init__.py +1 -0
  55. flask_appbuilder/security/sqla/apis/user/api.py +292 -0
  56. flask_appbuilder/security/sqla/apis/user/schema.py +97 -0
  57. flask_appbuilder/security/sqla/apis/user/validator.py +27 -0
  58. flask_appbuilder/security/sqla/apis/view_menu/__init__.py +1 -0
  59. flask_appbuilder/security/sqla/apis/view_menu/api.py +18 -0
  60. flask_appbuilder/security/sqla/manager.py +421 -203
  61. flask_appbuilder/security/sqla/models.py +192 -57
  62. flask_appbuilder/security/utils.py +9 -0
  63. flask_appbuilder/security/views.py +232 -229
  64. flask_appbuilder/static/.DS_Store +0 -0
  65. flask_appbuilder/static/appbuilder/css/ab.css +20 -12
  66. flask_appbuilder/static/appbuilder/css/bootstrap-datepicker/bootstrap-datepicker3.min.css +7 -0
  67. flask_appbuilder/static/appbuilder/css/bootstrap.min.css.map +1 -0
  68. flask_appbuilder/static/appbuilder/css/flags/flags16.css +249 -245
  69. flask_appbuilder/static/appbuilder/css/fontawesome/all.min.css +6 -0
  70. flask_appbuilder/static/appbuilder/css/fontawesome/brands.min.css +6 -0
  71. flask_appbuilder/static/appbuilder/css/fontawesome/fontawesome.min.css +6 -0
  72. flask_appbuilder/static/appbuilder/css/fontawesome/regular.min.css +6 -0
  73. flask_appbuilder/static/appbuilder/css/fontawesome/solid.min.css +6 -0
  74. flask_appbuilder/static/appbuilder/css/fontawesome/svg-with-js.min.css +6 -0
  75. flask_appbuilder/static/appbuilder/css/fontawesome/v4-font-face.min.css +6 -0
  76. flask_appbuilder/static/appbuilder/css/fontawesome/v4-shims.min.css +6 -0
  77. flask_appbuilder/static/appbuilder/css/fontawesome/v5-font-face.min.css +6 -0
  78. flask_appbuilder/static/appbuilder/css/images/flags16.png +0 -0
  79. flask_appbuilder/static/appbuilder/css/select2/select2-bootstrap.min.css +7 -0
  80. flask_appbuilder/static/appbuilder/css/select2/select2.min.css +1 -0
  81. flask_appbuilder/static/appbuilder/css/swagger/swagger-ui.css +3 -0
  82. flask_appbuilder/static/appbuilder/css/webfonts/fa-brands-400.ttf +0 -0
  83. flask_appbuilder/static/appbuilder/css/webfonts/fa-brands-400.woff2 +0 -0
  84. flask_appbuilder/static/appbuilder/css/webfonts/fa-regular-400.ttf +0 -0
  85. flask_appbuilder/static/appbuilder/css/webfonts/fa-regular-400.woff2 +0 -0
  86. flask_appbuilder/static/appbuilder/css/webfonts/fa-solid-900.ttf +0 -0
  87. flask_appbuilder/static/appbuilder/css/webfonts/fa-solid-900.woff2 +0 -0
  88. flask_appbuilder/static/appbuilder/css/webfonts/fa-v4compatibility.ttf +0 -0
  89. flask_appbuilder/static/appbuilder/css/webfonts/fa-v4compatibility.woff2 +0 -0
  90. flask_appbuilder/static/appbuilder/js/ab.js +33 -23
  91. flask_appbuilder/static/appbuilder/js/ab_filters.js +91 -84
  92. flask_appbuilder/static/appbuilder/js/bootstrap-datepicker/bootstrap-datepicker.min.js +8 -0
  93. flask_appbuilder/static/appbuilder/js/jquery-latest.js +2 -2
  94. flask_appbuilder/static/appbuilder/js/select2/select2.min.js +2 -0
  95. flask_appbuilder/static/appbuilder/js/swagger-ui-bundle.js +3 -0
  96. flask_appbuilder/templates/appbuilder/baselib.html +9 -3
  97. flask_appbuilder/templates/appbuilder/general/lib.html +60 -34
  98. flask_appbuilder/templates/appbuilder/general/model/edit.html +1 -1
  99. flask_appbuilder/templates/appbuilder/general/model/edit_cascade.html +1 -1
  100. flask_appbuilder/templates/appbuilder/general/model/search.html +3 -2
  101. flask_appbuilder/templates/appbuilder/general/model/show.html +1 -1
  102. flask_appbuilder/templates/appbuilder/general/model/show_cascade.html +1 -1
  103. flask_appbuilder/templates/appbuilder/general/security/login_db.html +7 -7
  104. flask_appbuilder/templates/appbuilder/general/security/login_ldap.html +5 -5
  105. flask_appbuilder/templates/appbuilder/general/security/login_oauth.html +24 -49
  106. flask_appbuilder/templates/appbuilder/general/widgets/base_list.html +2 -1
  107. flask_appbuilder/templates/appbuilder/general/widgets/chart.html +4 -2
  108. flask_appbuilder/templates/appbuilder/general/widgets/direct_chart.html +4 -3
  109. flask_appbuilder/templates/appbuilder/general/widgets/multiple_chart.html +3 -2
  110. flask_appbuilder/templates/appbuilder/general/widgets/search.html +11 -10
  111. flask_appbuilder/templates/appbuilder/init.html +37 -43
  112. flask_appbuilder/templates/appbuilder/navbar_menu.html +1 -1
  113. flask_appbuilder/templates/appbuilder/navbar_right.html +2 -2
  114. flask_appbuilder/templates/appbuilder/swagger/swagger.html +22 -19
  115. flask_appbuilder/translations/de/LC_MESSAGES/messages.mo +0 -0
  116. flask_appbuilder/translations/de/LC_MESSAGES/messages.po +305 -161
  117. flask_appbuilder/translations/fa/LC_MESSAGES/messages.mo +0 -0
  118. flask_appbuilder/translations/fa/LC_MESSAGES/messages.po +802 -0
  119. flask_appbuilder/translations/fr/LC_MESSAGES/messages.po +461 -319
  120. flask_appbuilder/translations/pt_BR/LC_MESSAGES/messages.po +650 -650
  121. flask_appbuilder/translations/ru/LC_MESSAGES/messages.po +1 -1
  122. flask_appbuilder/translations/sl/LC_MESSAGES/messages.mo +0 -0
  123. flask_appbuilder/translations/sl/LC_MESSAGES/messages.po +690 -0
  124. flask_appbuilder/translations/tr/LC_MESSAGES/messages.mo +0 -0
  125. flask_appbuilder/translations/tr/LC_MESSAGES/messages.po +1015 -0
  126. flask_appbuilder/upload.py +20 -22
  127. flask_appbuilder/urltools.py +39 -19
  128. flask_appbuilder/utils/base.py +76 -0
  129. flask_appbuilder/utils/legacy.py +33 -0
  130. flask_appbuilder/utils/limit.py +20 -0
  131. flask_appbuilder/validators.py +73 -14
  132. flask_appbuilder/views.py +75 -424
  133. flask_appbuilder/widgets.py +50 -51
  134. {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2.dist-info}/METADATA +36 -76
  135. flask_appbuilder-5.0.2.dist-info/RECORD +240 -0
  136. {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2.dist-info}/WHEEL +1 -1
  137. flask_appbuilder-5.0.2.dist-info/entry_points.txt +2 -0
  138. Flask_AppBuilder-3.2.1rc1.dist-info/RECORD +0 -270
  139. Flask_AppBuilder-3.2.1rc1.dist-info/entry_points.txt +0 -6
  140. flask_appbuilder/console.py +0 -426
  141. flask_appbuilder/models/mongoengine/__init__.py +0 -0
  142. flask_appbuilder/models/mongoengine/fields.py +0 -65
  143. flask_appbuilder/models/mongoengine/filters.py +0 -145
  144. flask_appbuilder/models/mongoengine/interface.py +0 -328
  145. flask_appbuilder/security/mongoengine/__init__.py +0 -0
  146. flask_appbuilder/security/mongoengine/manager.py +0 -402
  147. flask_appbuilder/security/mongoengine/models.py +0 -120
  148. flask_appbuilder/static/appbuilder/css/font-awesome.min.css +0 -4
  149. flask_appbuilder/static/appbuilder/datepicker/bootstrap-datepicker.css +0 -9
  150. flask_appbuilder/static/appbuilder/datepicker/bootstrap-datepicker.js +0 -28
  151. flask_appbuilder/static/appbuilder/fonts/FontAwesome.otf +0 -0
  152. flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.eot +0 -0
  153. flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.svg +0 -2671
  154. flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.ttf +0 -0
  155. flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.woff +0 -0
  156. flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.woff2 +0 -0
  157. flask_appbuilder/static/appbuilder/img/aol.png +0 -0
  158. flask_appbuilder/static/appbuilder/img/flags/flags16.png +0 -0
  159. flask_appbuilder/static/appbuilder/img/flickr.png +0 -0
  160. flask_appbuilder/static/appbuilder/img/google.png +0 -0
  161. flask_appbuilder/static/appbuilder/img/myopenid.png +0 -0
  162. flask_appbuilder/static/appbuilder/img/yahoo.png +0 -0
  163. flask_appbuilder/static/appbuilder/js/_google_charts.js +0 -39
  164. flask_appbuilder/static/appbuilder/js/html5shiv.js +0 -8
  165. flask_appbuilder/static/appbuilder/js/respond.min.js +0 -6
  166. flask_appbuilder/static/appbuilder/select2/select2-spinner.gif +0 -0
  167. flask_appbuilder/static/appbuilder/select2/select2.css +0 -1205
  168. flask_appbuilder/static/appbuilder/select2/select2.js +0 -23
  169. flask_appbuilder/static/appbuilder/select2/select2.png +0 -0
  170. flask_appbuilder/static/appbuilder/select2/select2x2.png +0 -0
  171. flask_appbuilder/templates/appbuilder/general/security/login_oid.html +0 -129
  172. flask_appbuilder/templates/appbuilder/general/security/resetpassword.html +0 -29
  173. flask_appbuilder/tests/__init__.py +0 -0
  174. flask_appbuilder/tests/__pycache__/__init__.cpython-36.pyc +0 -0
  175. flask_appbuilder/tests/__pycache__/__init__.cpython-37.pyc +0 -0
  176. flask_appbuilder/tests/__pycache__/_test_auth_ldap.cpython-37.pyc +0 -0
  177. flask_appbuilder/tests/__pycache__/_test_auth_oauth.cpython-37.pyc +0 -0
  178. flask_appbuilder/tests/__pycache__/_test_ldapsearch.cpython-36.pyc +0 -0
  179. flask_appbuilder/tests/__pycache__/_test_oauth_registration_role.cpython-36.pyc +0 -0
  180. flask_appbuilder/tests/__pycache__/base.cpython-36.pyc +0 -0
  181. flask_appbuilder/tests/__pycache__/base.cpython-37.pyc +0 -0
  182. flask_appbuilder/tests/__pycache__/config_api.cpython-36.pyc +0 -0
  183. flask_appbuilder/tests/__pycache__/config_api.cpython-37.pyc +0 -0
  184. flask_appbuilder/tests/__pycache__/const.cpython-36.pyc +0 -0
  185. flask_appbuilder/tests/__pycache__/const.cpython-37.pyc +0 -0
  186. flask_appbuilder/tests/__pycache__/test_0_fixture.cpython-36.pyc +0 -0
  187. flask_appbuilder/tests/__pycache__/test_0_fixture.cpython-37.pyc +0 -0
  188. flask_appbuilder/tests/__pycache__/test_api.cpython-36.pyc +0 -0
  189. flask_appbuilder/tests/__pycache__/test_api.cpython-37.pyc +0 -0
  190. flask_appbuilder/tests/__pycache__/test_fab_cli.cpython-36.pyc +0 -0
  191. flask_appbuilder/tests/__pycache__/test_fab_cli.cpython-37.pyc +0 -0
  192. flask_appbuilder/tests/__pycache__/test_menu.cpython-36.pyc +0 -0
  193. flask_appbuilder/tests/__pycache__/test_menu.cpython-37.pyc +0 -0
  194. flask_appbuilder/tests/__pycache__/test_mongoengine.cpython-36.pyc +0 -0
  195. flask_appbuilder/tests/__pycache__/test_mvc.cpython-36.pyc +0 -0
  196. flask_appbuilder/tests/__pycache__/test_mvc.cpython-37.pyc +0 -0
  197. flask_appbuilder/tests/__pycache__/test_sqlalchemy.cpython-36.pyc +0 -0
  198. flask_appbuilder/tests/__pycache__/test_sqlalchemy.cpython-37.pyc +0 -0
  199. flask_appbuilder/tests/_test_auth_ldap.py +0 -1045
  200. flask_appbuilder/tests/_test_auth_oauth.py +0 -419
  201. flask_appbuilder/tests/_test_ldapsearch.py +0 -135
  202. flask_appbuilder/tests/_test_oauth_registration_role.py +0 -59
  203. flask_appbuilder/tests/app.db +0 -0
  204. flask_appbuilder/tests/base.py +0 -90
  205. flask_appbuilder/tests/config_api.py +0 -21
  206. flask_appbuilder/tests/const.py +0 -9
  207. flask_appbuilder/tests/mongoengine/__init__.py +0 -0
  208. flask_appbuilder/tests/mongoengine/__pycache__/__init__.cpython-36.pyc +0 -0
  209. flask_appbuilder/tests/mongoengine/__pycache__/__init__.cpython-37.pyc +0 -0
  210. flask_appbuilder/tests/mongoengine/__pycache__/models.cpython-36.pyc +0 -0
  211. flask_appbuilder/tests/mongoengine/models.py +0 -41
  212. flask_appbuilder/tests/sqla/__init__.py +0 -0
  213. flask_appbuilder/tests/sqla/__pycache__/__init__.cpython-36.pyc +0 -0
  214. flask_appbuilder/tests/sqla/__pycache__/__init__.cpython-37.pyc +0 -0
  215. flask_appbuilder/tests/sqla/__pycache__/models.cpython-36.pyc +0 -0
  216. flask_appbuilder/tests/sqla/__pycache__/models.cpython-37.pyc +0 -0
  217. flask_appbuilder/tests/sqla/models.py +0 -340
  218. flask_appbuilder/tests/test_0_fixture.py +0 -39
  219. flask_appbuilder/tests/test_api.py +0 -2790
  220. flask_appbuilder/tests/test_fab_cli.py +0 -72
  221. flask_appbuilder/tests/test_menu.py +0 -122
  222. flask_appbuilder/tests/test_mongoengine.py +0 -572
  223. flask_appbuilder/tests/test_mvc.py +0 -1710
  224. flask_appbuilder/tests/test_sqlalchemy.py +0 -24
  225. flask_appbuilder/translations/__pycache__/__init__.cpython-36.pyc +0 -0
  226. flask_appbuilder/translations/es/LC_MESSAGES/messages.po~ +0 -582
  227. {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2.dist-info}/LICENSE +0 -0
  228. {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2.dist-info}/top_level.txt +0 -0
@@ -1,21 +0,0 @@
1
- import os
2
-
3
- basedir = os.path.abspath(os.path.dirname(__file__))
4
-
5
- SQLALCHEMY_DATABASE_URI = os.environ.get(
6
- "SQLALCHEMY_DATABASE_URI"
7
- ) or "sqlite:///" + os.path.join(basedir, "app.db")
8
-
9
-
10
- SECRET_KEY = "thisismyscretkey"
11
- SQLALCHEMY_TRACK_MODIFICATIONS = False
12
- WTF_CSRF_ENABLED = False
13
- FAB_API_SWAGGER_UI = True
14
- FAB_ROLES = {
15
- "ReadOnly": [
16
- [".*", "can_get"],
17
- [".*", "can_info"],
18
- [".*", "can_list"],
19
- [".*", "can_show"],
20
- ]
21
- }
@@ -1,9 +0,0 @@
1
- MODEL1_DATA_SIZE = 30
2
- MODEL2_DATA_SIZE = 30
3
- MODELOMCHILD_DATA_SIZE = 30
4
-
5
- USERNAME_ADMIN = "testadmin"
6
- PASSWORD_ADMIN = "password"
7
- MAX_PAGE_SIZE = 25
8
- USERNAME_READONLY = "readonly"
9
- PASSWORD_READONLY = "readonly"
File without changes
@@ -1,41 +0,0 @@
1
- from mongoengine import (
2
- DateTimeField,
3
- FileField,
4
- FloatField,
5
- ImageField,
6
- IntField,
7
- ReferenceField,
8
- StringField,
9
- )
10
- from mongoengine import Document
11
-
12
-
13
- class Model1(Document):
14
- field_string = StringField(unique=True, required=True)
15
- field_integer = IntField()
16
- field_float = FloatField()
17
- field_date = DateTimeField()
18
- field_file = FileField()
19
- field_image = ImageField()
20
-
21
- def __repr__(self):
22
- return str(self.field_string)
23
-
24
- def __unicode__(self):
25
- return self.field_string
26
-
27
-
28
- class Model2(Document):
29
- field_string = StringField(unique=True, required=True)
30
- field_integer = IntField()
31
- field_float = FloatField()
32
- field_date = DateTimeField()
33
- excluded_string = StringField(default="EXCLUDED")
34
- default_string = StringField(default="DEFAULT")
35
- group = ReferenceField(Model1, required=True)
36
-
37
- def __repr__(self):
38
- return str(self.field_string)
39
-
40
- def field_method(self):
41
- return "field_method_value"
File without changes
@@ -1,340 +0,0 @@
1
- import datetime
2
- import enum
3
-
4
- from flask_appbuilder import Model
5
- from flask_appbuilder.api.schemas import BaseModelSchema
6
- from marshmallow import fields, ValidationError
7
- from sqlalchemy import (
8
- Column,
9
- Date,
10
- DateTime,
11
- Enum,
12
- Float,
13
- ForeignKey,
14
- Integer,
15
- String,
16
- Table,
17
- UniqueConstraint,
18
- )
19
- from sqlalchemy.orm import backref, relationship
20
-
21
- from ..const import MODELOMCHILD_DATA_SIZE
22
-
23
-
24
- def validate_name(n):
25
- if n[0] != "A":
26
- raise ValidationError("Name must start with an A")
27
-
28
-
29
- class Model1(Model):
30
- id = Column(Integer, primary_key=True)
31
- field_string = Column(String(50), unique=True, nullable=False)
32
- field_integer = Column(Integer())
33
- field_float = Column(Float())
34
- field_date = Column(Date())
35
-
36
- def __repr__(self):
37
- return str(self.field_string)
38
-
39
- def full_concat(self):
40
- return (
41
- f"{self.field_string}.{self.field_integer}"
42
- f".{self.field_float}.{self.field_date}"
43
- )
44
-
45
-
46
- def validate_field_string(n):
47
- if n[0] != "A":
48
- raise ValidationError("Name must start with an A")
49
-
50
-
51
- class Model1CustomSchema(BaseModelSchema):
52
- model_cls = Model1
53
- field_string = fields.String(validate=validate_name)
54
- field_integer = fields.Integer(allow_none=True)
55
- field_float = fields.Float(allow_none=True)
56
- field_date = fields.Date(allow_none=True)
57
-
58
-
59
- class Model2(Model):
60
- id = Column(Integer, primary_key=True)
61
- field_string = Column(String(50), unique=True, nullable=False)
62
- field_integer = Column(Integer())
63
- field_float = Column(Float())
64
- field_date = Column(Date())
65
- excluded_string = Column(String(50), default="EXCLUDED")
66
- default_string = Column(String(50), default="DEFAULT")
67
- group_id = Column(Integer, ForeignKey("model1.id"), nullable=False)
68
- group = relationship("Model1")
69
-
70
- def __repr__(self):
71
- return str(self.field_string)
72
-
73
- def field_method(self):
74
- return f"{self.field_string}_field_method"
75
-
76
-
77
- class Model3(Model):
78
- pk1 = Column(Integer(), primary_key=True)
79
- pk2 = Column(DateTime(), primary_key=True)
80
- field_string = Column(String(50), unique=True, nullable=False)
81
-
82
- def __repr__(self):
83
- return str(self.field_string)
84
-
85
-
86
- class Model4(Model):
87
- id = Column(Integer(), primary_key=True)
88
- field_string = Column(String(50), unique=True, nullable=False)
89
- model1_1_id = Column(Integer, ForeignKey("model1.id"), nullable=False)
90
- model1_1 = relationship("Model1", foreign_keys=[model1_1_id])
91
- model1_2_id = Column(Integer, ForeignKey("model1.id"), nullable=False)
92
- model1_2 = relationship("Model1", foreign_keys=[model1_2_id])
93
-
94
- def __repr__(self):
95
- return str(self.field_string)
96
-
97
-
98
- class ModelWithProperty(Model):
99
- id = Column(Integer, primary_key=True)
100
- field_string = Column(String(50), unique=True, nullable=False)
101
-
102
- @property
103
- def custom_property(self):
104
- return self.field_string + "_custom"
105
-
106
-
107
- class TmpEnum(enum.Enum):
108
- e1 = "a"
109
- e2 = 2
110
- e3 = 3
111
-
112
-
113
- class ModelWithEnums(Model):
114
- id = Column(Integer, primary_key=True)
115
- enum1 = Column(Enum("e1", "e2", "e3", name="enum1"))
116
- enum2 = Column(Enum(TmpEnum), info={"enum_class": TmpEnum})
117
-
118
-
119
- assoc_parent_child = Table(
120
- "parent_child",
121
- Model.metadata,
122
- Column("id", Integer, primary_key=True),
123
- Column("parent_id", Integer, ForeignKey("parent.id")),
124
- Column("child_id", Integer, ForeignKey("child.id")),
125
- UniqueConstraint("parent_id", "child_id"),
126
- )
127
-
128
-
129
- class ModelMMParent(Model):
130
- __tablename__ = "parent"
131
- id = Column(Integer, primary_key=True)
132
- field_string = Column(String(50), unique=True, nullable=False)
133
- children = relationship("ModelMMChild", secondary=assoc_parent_child)
134
-
135
-
136
- class ModelMMChild(Model):
137
- __tablename__ = "child"
138
- id = Column(Integer, primary_key=True)
139
- field_string = Column(String(50), unique=True, nullable=False)
140
- field_integer = Column(Integer())
141
-
142
-
143
- assoc_parent_child_required = Table(
144
- "parent_child_required",
145
- Model.metadata,
146
- Column("id", Integer, primary_key=True),
147
- Column("parent_id", Integer, ForeignKey("parent_required.id")),
148
- Column("child_id", Integer, ForeignKey("child_required.id")),
149
- UniqueConstraint("parent_id", "child_id"),
150
- )
151
-
152
-
153
- class ModelMMParentRequired(Model):
154
- __tablename__ = "parent_required"
155
- id = Column(Integer, primary_key=True)
156
- field_string = Column(String(50), unique=True, nullable=False)
157
- children = relationship(
158
- "ModelMMChildRequired",
159
- secondary=assoc_parent_child_required,
160
- info={"required": True},
161
- )
162
-
163
-
164
- class ModelMMChildRequired(Model):
165
- __tablename__ = "child_required"
166
- id = Column(Integer, primary_key=True)
167
- field_string = Column(String(50), unique=True, nullable=False)
168
-
169
-
170
- class ModelOMParent(Model):
171
- __tablename__ = "model_om_parent"
172
- id = Column(Integer, primary_key=True)
173
- field_string = Column(String(50), unique=True, nullable=False)
174
-
175
-
176
- class ModelOMChild(Model):
177
- id = Column(Integer, primary_key=True)
178
- field_string = Column(String(50), unique=True, nullable=False)
179
- parent_id = Column(Integer, ForeignKey("model_om_parent.id"))
180
- parent = relationship(
181
- "ModelOMParent",
182
- backref=backref("children", cascade="all, delete-orphan"),
183
- foreign_keys=[parent_id],
184
- )
185
-
186
- """ ---------------------------------
187
- TEST HELPER FUNCTIONS
188
- ---------------------------------
189
- """
190
-
191
-
192
- def insert_model1(session, i=0):
193
- add_flag = False
194
- model = session.query(Model1).filter_by(id=i + 1).one_or_none()
195
- if not model:
196
- model = Model1()
197
- add_flag = True
198
- model.field_string = f"test{i}"
199
- model.field_integer = i
200
- model.field_float = float(i)
201
- if add_flag:
202
- session.add(model)
203
- session.commit()
204
- return model
205
-
206
-
207
- def insert_model2(session, i=0, model1_collection=None):
208
- if not model1_collection:
209
- model1 = session.query(Model1).filter_by(id=i + 1).one_or_none()
210
- else:
211
- model1 = model1_collection[i]
212
- model = Model2()
213
- model.field_string = f"test{i}"
214
- model.field_integer = i
215
- model.field_float = float(i)
216
- model.group = model1
217
-
218
- import random
219
-
220
- year = random.choice(range(1900, 2012))
221
- month = random.choice(range(1, 12))
222
- day = random.choice(range(1, 28))
223
- model.field_date = datetime.datetime(year, month, day)
224
-
225
- session.add(model)
226
- session.commit()
227
- return model
228
-
229
-
230
- def insert_model3(session):
231
- model3 = Model3(pk1=3, pk2=datetime.datetime(2017, 3, 3), field_string="foo")
232
- try:
233
- session.add(model3)
234
- session.commit()
235
- except Exception as e:
236
- print("Error {0}".format(str(e)))
237
- session.rollback()
238
-
239
-
240
- def insert_model_mm_parent(session, i=0, children=None):
241
- add_flag = False
242
- model = session.query(ModelMMParent).filter_by(id=i + 1).one_or_none()
243
- if not model:
244
- model = ModelMMParent()
245
- add_flag = True
246
- model.field_string = str(i)
247
- if children:
248
- model.children = children
249
- if add_flag:
250
- session.add(model)
251
- session.commit()
252
- return model
253
-
254
-
255
- def insert_model_with_enums(session, i=0):
256
- add_flag = False
257
- model = session.query(ModelWithEnums).filter_by(id=i + 1).one_or_none()
258
- if not model:
259
- model = ModelWithEnums()
260
- add_flag = True
261
- model.enum1 = "e1"
262
- model.enum2 = TmpEnum.e2
263
- if add_flag:
264
- session.add(model)
265
- session.commit()
266
- return model
267
-
268
-
269
- def insert_data(session, count):
270
- model1_collection = list()
271
- # Fill model1
272
- for i in range(count):
273
- model = insert_model1(session, i)
274
- model1_collection.append(model)
275
- # Fill model2
276
- for i in range(count):
277
- insert_model2(session, i=i, model1_collection=model1_collection)
278
- insert_model3(session)
279
-
280
- for i in range(count):
281
- model = ModelWithEnums()
282
- model.enum1 = "e1"
283
- model.enum2 = TmpEnum.e2
284
- session.add(model)
285
- session.commit()
286
- # Fill Model4
287
- for i in range(count):
288
- model = Model4()
289
- model.field_string = f"test{i}"
290
- model.model1_1 = model1_collection[i]
291
- model.model1_2 = model1_collection[i]
292
- session.add(model)
293
- session.commit()
294
-
295
- children = list()
296
- children_required = list()
297
- for i in range(1, 4):
298
- model = ModelMMChild()
299
- model.field_string = str(i)
300
- model.field_integer = i
301
- children.append(model)
302
- session.add(model)
303
- session.commit()
304
-
305
- model = ModelMMChildRequired()
306
- model.field_string = str(i)
307
- children_required.append(model)
308
- session.add(model)
309
- session.commit()
310
-
311
- for i in range(count):
312
- insert_model_mm_parent(session, i=i, children=children)
313
-
314
- model = ModelMMParentRequired()
315
- model.field_string = str(i)
316
- model.children = children_required
317
- session.add(model)
318
- session.commit()
319
-
320
- for i in range(count):
321
- model = ModelWithProperty()
322
- model.field_string = str(i)
323
- session.add(model)
324
- session.commit()
325
-
326
- model_om_parents = list()
327
- for i in range(count):
328
- model = ModelOMParent()
329
- model.field_string = f"text{i}"
330
- session.add(model)
331
- session.commit()
332
- model_om_parents.append(model)
333
-
334
- for i in range(count):
335
- for j in range(1, MODELOMCHILD_DATA_SIZE):
336
- model = ModelOMChild()
337
- model.field_string = f"text{i}.{j}"
338
- model.parent = model_om_parents[i]
339
- session.add(model)
340
- session.commit()
@@ -1,39 +0,0 @@
1
- from flask_appbuilder import SQLA
2
-
3
- from .base import FABTestCase
4
- from .const import (
5
- MODEL1_DATA_SIZE,
6
- PASSWORD_ADMIN,
7
- PASSWORD_READONLY,
8
- USERNAME_ADMIN,
9
- USERNAME_READONLY,
10
- )
11
- from .sqla.models import insert_data
12
-
13
-
14
- class TestData(FABTestCase):
15
- def setUp(self):
16
- from flask import Flask
17
- from flask_appbuilder import AppBuilder
18
-
19
- self.app = Flask(__name__)
20
- self.app.config.from_object("flask_appbuilder.tests.config_api")
21
- self.db = SQLA(self.app)
22
- self.appbuilder = AppBuilder(self.app, self.db.session)
23
-
24
- def test_data(self):
25
- insert_data(self.db.session, MODEL1_DATA_SIZE)
26
-
27
- def test_create_admin(self):
28
- self.create_admin_user(self.appbuilder, USERNAME_ADMIN, PASSWORD_ADMIN)
29
-
30
- def test_create_ro_user(self):
31
- self.create_user(
32
- self.appbuilder,
33
- USERNAME_READONLY,
34
- PASSWORD_READONLY,
35
- "ReadOnly",
36
- first_name="readonly",
37
- last_name="readonly",
38
- email="readonly@fab.org",
39
- )