brilliance-admin 0.42.0__tar.gz → 0.43.1__tar.gz

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 (136) hide show
  1. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/.isort.cfg +1 -1
  2. brilliance_admin-0.43.1/PKG-INFO +214 -0
  3. brilliance_admin-0.43.1/README.md +183 -0
  4. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/__init__.py +2 -2
  5. brilliance_admin-0.43.1/brilliance_admin/api/routers.py +18 -0
  6. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/api/utils.py +1 -1
  7. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/api/views/auth.py +6 -6
  8. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/api/views/autocomplete.py +9 -9
  9. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/api/views/graphs.py +8 -8
  10. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/api/views/index.py +11 -4
  11. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/api/views/schema.py +3 -3
  12. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/api/views/settings.py +5 -5
  13. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/api/views/table.py +23 -23
  14. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/auth.py +1 -1
  15. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/exceptions.py +3 -4
  16. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/sqlalchemy/auth.py +4 -4
  17. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/sqlalchemy/autocomplete.py +4 -4
  18. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/sqlalchemy/fields.py +10 -10
  19. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/sqlalchemy/fields_schema.py +6 -6
  20. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/sqlalchemy/table/base.py +4 -4
  21. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/sqlalchemy/table/create.py +7 -7
  22. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/sqlalchemy/table/delete.py +3 -3
  23. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/sqlalchemy/table/list.py +7 -7
  24. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/sqlalchemy/table/retrieve.py +6 -6
  25. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/sqlalchemy/table/update.py +6 -6
  26. brilliance_admin-0.43.1/brilliance_admin/locales/en.yml +22 -0
  27. brilliance_admin-0.43.1/brilliance_admin/locales/ru.yml +22 -0
  28. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/admin_schema.py +39 -31
  29. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/category.py +8 -8
  30. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/graphs/category_graphs.py +10 -9
  31. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/group.py +10 -10
  32. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/table/admin_action.py +8 -7
  33. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/table/category_table.py +21 -21
  34. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/table/fields/base.py +21 -21
  35. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/table/fields/function_field.py +3 -3
  36. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/table/fields_schema.py +9 -9
  37. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/table/table_models.py +1 -1
  38. brilliance_admin-0.42.0/admin_panel/static/index-BeniOHDv.js → brilliance_admin-0.43.1/brilliance_admin/static/index-D9axz5zK.js +24 -24
  39. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/templates/index.html +1 -1
  40. brilliance_admin-0.43.1/brilliance_admin/translations.py +115 -0
  41. brilliance_admin-0.43.1/brilliance_admin/utils.py +153 -0
  42. brilliance_admin-0.43.1/brilliance_admin.egg-info/PKG-INFO +214 -0
  43. brilliance_admin-0.43.1/brilliance_admin.egg-info/SOURCES.txt +123 -0
  44. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/brilliance_admin.egg-info/requires.txt +4 -3
  45. brilliance_admin-0.43.1/brilliance_admin.egg-info/top_level.txt +1 -0
  46. brilliance_admin-0.43.1/example/locales/en.yml +52 -0
  47. brilliance_admin-0.43.1/example/locales/ru.yml +51 -0
  48. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/main.py +17 -18
  49. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/sections/currency.py +4 -3
  50. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/sections/graphs.py +3 -3
  51. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/sections/merchant.py +2 -2
  52. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/sections/models.py +1 -1
  53. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/sections/payments.py +10 -10
  54. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/sections/terminal.py +2 -2
  55. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/sections/users.py +2 -2
  56. brilliance_admin-0.43.1/example/static/favicon.ico +0 -0
  57. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/pyproject.toml +8 -7
  58. brilliance_admin-0.43.1/screenshots/PC-graphs.jpeg +0 -0
  59. brilliance_admin-0.43.1/screenshots/PC-table.jpeg +0 -0
  60. brilliance_admin-0.43.1/screenshots/iPad-edit.jpeg +0 -0
  61. brilliance_admin-0.43.1/screenshots/iPhone 15-edit.jpeg +0 -0
  62. brilliance_admin-0.43.1/screenshots/iPhone 15-login.jpeg +0 -0
  63. brilliance_admin-0.43.1/screenshots/websitemockupgenerator.png +0 -0
  64. brilliance_admin-0.43.1/tests/conftest.py +26 -0
  65. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/tests/test_action.py +1 -1
  66. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/tests/test_payments_fields_schema.py +3 -5
  67. brilliance_admin-0.42.0/tests/test_index_context_data.py → brilliance_admin-0.43.1/tests/test_settings.py +17 -1
  68. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/tests/test_sqlalcmeny_auth.py +4 -4
  69. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/tests/test_sqlalcmeny_crud.py +15 -23
  70. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/tests/test_sqlalcmeny_filters.py +15 -21
  71. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/tests/test_sqlalcmeny_schema.py +4 -6
  72. brilliance_admin-0.43.1/tests/test_translations.py +40 -0
  73. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/uv.lock +232 -119
  74. brilliance_admin-0.42.0/PKG-INFO +0 -155
  75. brilliance_admin-0.42.0/README.md +0 -125
  76. brilliance_admin-0.42.0/admin_panel/api/routers.py +0 -18
  77. brilliance_admin-0.42.0/admin_panel/translations.py +0 -145
  78. brilliance_admin-0.42.0/admin_panel/utils.py +0 -50
  79. brilliance_admin-0.42.0/brilliance_admin.egg-info/PKG-INFO +0 -155
  80. brilliance_admin-0.42.0/brilliance_admin.egg-info/SOURCES.txt +0 -113
  81. brilliance_admin-0.42.0/brilliance_admin.egg-info/top_level.txt +0 -1
  82. brilliance_admin-0.42.0/example/phrases.py +0 -112
  83. brilliance_admin-0.42.0/tests/conftest.py +0 -12
  84. brilliance_admin-0.42.0/tests/test_translations.py +0 -90
  85. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/.configs/docker/Dockerfile +0 -0
  86. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/.configs/docker/docker-compose.yml +0 -0
  87. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/.configs/nginx/example.conf +0 -0
  88. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/.env +0 -0
  89. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/.github/workflows/certbot.yml +0 -0
  90. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/.github/workflows/deploy.yml +0 -0
  91. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/.github/workflows/install-docker.yml +0 -0
  92. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/.gitignore +0 -0
  93. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/.python-version +0 -0
  94. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/LICENSE +0 -0
  95. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/api/__init__.py +0 -0
  96. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/api/views/__init__.py +0 -0
  97. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/docs.py +0 -0
  98. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/__init__.py +0 -0
  99. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/sqlalchemy/__init__.py +0 -0
  100. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/integrations/sqlalchemy/table/__init__.py +0 -0
  101. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/__init__.py +0 -0
  102. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/graphs/__init__.py +0 -0
  103. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/table/__init__.py +0 -0
  104. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/schema/table/fields/__init__.py +0 -0
  105. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/index-vlBToOhT.css +0 -0
  106. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/materialdesignicons-webfont-CYDMK1kx.woff2 +0 -0
  107. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/materialdesignicons-webfont-CgCzGbLl.woff +0 -0
  108. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/materialdesignicons-webfont-D3kAzl71.ttf +0 -0
  109. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/materialdesignicons-webfont-DttUABo4.eot +0 -0
  110. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/dark-first/content.min.css +0 -0
  111. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/dark-first/skin.min.css +0 -0
  112. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/dark-slim/content.min.css +0 -0
  113. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/dark-slim/skin.min.css +0 -0
  114. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/img/example.png +0 -0
  115. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/img/tinymce.woff2 +0 -0
  116. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/lightgray/content.min.css +0 -0
  117. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/lightgray/fonts/tinymce.woff +0 -0
  118. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/lightgray/skin.min.css +0 -0
  119. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/plugins/accordion/css/accordion.css +0 -0
  120. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/plugins/accordion/plugin.js +0 -0
  121. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/plugins/codesample/css/prism.css +0 -0
  122. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/plugins/customLink/css/link.css +0 -0
  123. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/plugins/customLink/plugin.js +0 -0
  124. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/tinymce/tinymce.min.js +0 -0
  125. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/brilliance_admin}/static/vanilla-picker-B6E6ObS_.js +0 -0
  126. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/brilliance_admin.egg-info/dependency_links.txt +0 -0
  127. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/README.md +0 -0
  128. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/__init__.py +0 -0
  129. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/sections/__init__.py +0 -0
  130. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/sqlite.py +0 -0
  131. {brilliance_admin-0.42.0/admin_panel → brilliance_admin-0.43.1/example}/static/favicon.jpg +0 -0
  132. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/static/logo-outline.png +0 -0
  133. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/static/logo.png +0 -0
  134. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/example/utils.py +0 -0
  135. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/setup.cfg +0 -0
  136. {brilliance_admin-0.42.0 → brilliance_admin-0.43.1}/tests/__init__.py +0 -0
@@ -3,5 +3,5 @@ line_length=120
3
3
  py_version=39
4
4
  multi_line_output=4
5
5
  known_third_party=fastapi
6
- known_first_party=app,tests
6
+ known_first_party=app,tests,brilliance_admin
7
7
  virtual_env=py3
@@ -0,0 +1,214 @@
1
+ Metadata-Version: 2.4
2
+ Name: brilliance-admin
3
+ Version: 0.43.1
4
+ Summary: Simple and lightweight admin panel framework powered by FastAPI and Vue3 Vuetify together.. Some call it heavenly in its brilliance.
5
+ License-Expression: AGPL-3.0
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: asgiref>=3.11
10
+ Requires-Dist: fastapi>=0.115
11
+ Requires-Dist: jinja2>=3.1
12
+ Requires-Dist: PyYAML>=6.0
13
+ Provides-Extra: example
14
+ Requires-Dist: uvicorn>=0.34.0; extra == "example"
15
+ Requires-Dist: faker>=38.2.0; extra == "example"
16
+ Requires-Dist: pyjwt>=2.10.1; extra == "example"
17
+ Requires-Dist: structlog>=25.5.0; extra == "example"
18
+ Requires-Dist: rich>=14.2.0; extra == "example"
19
+ Provides-Extra: tests
20
+ Requires-Dist: pytest>=8.4.2; extra == "tests"
21
+ Requires-Dist: pytest-asyncio>=1.2.0; extra == "tests"
22
+ Requires-Dist: httpx>=0.28.1; extra == "tests"
23
+ Requires-Dist: pytest-mock>=3.15.1; extra == "tests"
24
+ Requires-Dist: sqlalchemy>=2.0.41; extra == "tests"
25
+ Requires-Dist: aiosqlite>=0.22.1; extra == "tests"
26
+ Requires-Dist: factory-boy>=3.3.3; extra == "tests"
27
+ Requires-Dist: pyjwt>=2.10.1; extra == "tests"
28
+ Provides-Extra: scalar
29
+ Requires-Dist: scalar-fastapi>=1.5.0; extra == "scalar"
30
+ Dynamic: license-file
31
+
32
+ <div align="center">
33
+ <img src="https://github.com/brilliance-admin/backend-python/blob/main/example/static/logo-outline.png?raw=true"
34
+ alt="Brilliance Admin"
35
+ width="600">
36
+
37
+ [![PyPI](https://img.shields.io/pypi/v/brilliance-admin)](https://pypi.org/project/brilliance-admin/)
38
+ [![CI](https://github.com/brilliance-admin/backend-python/actions/workflows/deploy.yml/badge.svg)](https://github.com/brilliance-admin/backend-python/actions)
39
+
40
+ Simple and lightweight admin panel framework powered by `FastAPI` and `Vue3` `Vuetify` together. \
41
+ Integrated with `SQLAlchemy`. Inspaired by Django Admin and DRF.\
42
+ _Some call it heavenly in its brilliance._
43
+
44
+ ### [Live Demo](https://brilliance-admin.com/) | [Demo Sources](https://github.com/brilliance-admin/backend-python/tree/main/example) | Documentation (todo)
45
+
46
+ <img src="https://github.com/brilliance-admin/backend-python/blob/main/screenshots/websitemockupgenerator.png?raw=true"
47
+ alt="Preview">
48
+
49
+ </div>
50
+
51
+ **Key ideas:**
52
+ - **API oriented**\
53
+ Works entirely on FastAPI and provides a prebuilt SPA [frontend](https://github.com/brilliance-admin/frontend) via static files (Vue3 + Vuetify). No separate startup is required.
54
+ > Data generation/updating API separated from rendering fontend with zero hardcode, this makes it possible to have a single frontend with multiple backend implementations in different languages and makes test coverage easier.
55
+ - **Rich visualization**\
56
+ Providing rich and convenient ways to display and manage data (tables, charts, etc) from any data source.
57
+ - **ORM**\
58
+ Automatic schema generation and methods for CRUD operations.
59
+ - **Minimal boilerplate**\
60
+ Focused on simplified, but rich configuration.
61
+
62
+ **How it works:**
63
+ - After authentication, the user receives the admin panel schema, and the frontend renders it
64
+ - The frontend communicates with the backend via API to fetch and modify data
65
+
66
+ ### Features:
67
+
68
+ * Tables with full CRUD support, including filtering, sorting, and pagination.
69
+ * Ability to define custom table actions with forms, response messages, and file downloads.
70
+ * Graphs via ChartJS
71
+ * Localization support
72
+ * Adapted for different screen sizes and mobile devices
73
+ * Authorization via any account data source
74
+
75
+ **Integrations:**
76
+ * **SQLAlchemy** - schema autogeneration for tables + CRUD operations + authorization
77
+
78
+ **Planned:**
79
+ * Role-based access control system
80
+ * Nested data support for creation and detail views
81
+ * Django ORM inegration
82
+
83
+ ## How to use it
84
+
85
+ Installation:
86
+ ``` shell
87
+ pip install brilliance-admin
88
+ ```
89
+
90
+ You need to generate `AdminSchema` instance:
91
+ ``` python
92
+ from brilliance_admin import schema
93
+
94
+
95
+ class CategoryExample(schema.CategoryTable):
96
+ "Implementation of get_list and retrieve; update and create are optional"
97
+
98
+
99
+ admin_schema = schema.AdminSchema(
100
+ title='Admin Panel',
101
+ auth=YourAdminAuthentication(),
102
+ groups=[
103
+ schema.Group(
104
+ slug='example',
105
+ title='Example',
106
+ icon='mdi-star',
107
+ categories=[
108
+ CategoryExample(),
109
+ ]
110
+ ),
111
+ ],
112
+ )
113
+
114
+ admin_app = admin_schema.generate_app()
115
+
116
+ # Your FastAPI app
117
+ app = FastAPI()
118
+ app.mount('/admin', admin_app)
119
+ ```
120
+
121
+ ## SQLAlchemy integration
122
+
123
+ Supports automatic schema generation for CRUD tables:
124
+
125
+ ``` python
126
+ category = sqlalchemy.SQLAlchemyAdmin(db_async_session=async_sessionmaker, model=Terminal)
127
+ ```
128
+
129
+ > [!NOTE]
130
+ > If `table_schema` is not specified, it will be generated automatically with all discovered fields and relationships
131
+
132
+ Now, the `category` instance can be passed to `categories`.
133
+
134
+ ### DRF class style schema
135
+
136
+ ``` python
137
+ from brilliance_admin import sqlalchemy
138
+ from brilliance_admin.translations import TranslateText as _
139
+
140
+ from your_project.models import Terminal
141
+
142
+
143
+ class TerminalFiltersSchema(sqlalchemy.SQLAlchemyFieldsSchema):
144
+ model = Terminal
145
+ fields = ['id', 'created_at']
146
+ created_at = schema.DateTimeField(range=True)
147
+
148
+
149
+ class TerminalSchema(sqlalchemy.SQLAlchemyFieldsSchema):
150
+ model = Terminal
151
+ list_display = ['id', 'merchant_id']
152
+
153
+
154
+ class TerminalAdmin(sqlalchemy.SQLAlchemyAdmin):
155
+ db_async_session = async_sessionmaker
156
+ model = Terminal
157
+ title = _('terminals')
158
+ icon = 'mdi-console-network-outline'
159
+
160
+ ordering_fields = ['id']
161
+ search_fields = ['id', 'title']
162
+
163
+ table_schema = TerminalSchema()
164
+ table_filters = TerminalFiltersSchema()
165
+
166
+
167
+ category = TerminalAdmin()
168
+ ```
169
+
170
+ ### Can be used both via inheritance and instancing
171
+
172
+ Optionally, functional-style generation can be used to reduce boilerplate code
173
+
174
+ Availiable for `SQLAlchemyAdmin` and `SQLAlchemyFieldsSchema`
175
+
176
+ ``` python
177
+ category = sqlalchemy.SQLAlchemyAdmin(
178
+ db_async_session=async_sessionmaker,
179
+ model=Terminal,
180
+
181
+ table_schema = sqlalchemy.SQLAlchemyFieldsSchema(
182
+ model=Terminal,
183
+ list_display=['id', 'merchant_id'],
184
+ ),
185
+ table_filters = sqlalchemy.SQLAlchemyFieldsSchema(
186
+ model=Terminal,
187
+ fields=['id', 'created_at'],
188
+ created_at=schema.DateTimeField(range=True),
189
+ ),
190
+ )
191
+ ```
192
+
193
+ ### SQLAlchemy JWT Authentication
194
+
195
+ ``` python
196
+ auth = sqlalchemy.SQLAlchemyJWTAdminAuthentication(
197
+ secret='auth_secret',
198
+ db_async_session=async_session,
199
+ user_model=User,
200
+ )
201
+ ```
202
+
203
+ ## Comparison of Similar Projects
204
+
205
+ | Criterion | Brilliance Admin | Django Admin/Unfold | FastAPI Admin | Starlette Admin |
206
+ |---------|------------------|---------------|---------------|-----------------|
207
+ | Base framework | FastAPI | Django | FastAPI | Starlette / FastAPI |
208
+ | Rendering model | Prebuilt Vue 3 + Vuetify SPA + Jinja2 | Server-side Django templates | Server-side Jinja2 templates + Tabler UI | Server-side Jinja2 templates + Tabler UI |
209
+ | Frontend architecture | Separate frontend (SPA) | Classic server-rendered UI | Server-rendered UI with JS interactivity | Server-rendered UI with JS interactivity |
210
+ | Data source | Any source + SQLAlchemy | Django ORM | Tortoise ORM | Any source + SQLAlchemy, MongoDB |
211
+ | Multiple databases per model | Yes | Database routers | No (global engine) | Yes (session per ModelView) |
212
+ | Schema generation | User-defined format | From Django models | From ORM models | User-defined format |
213
+ | Async support | Yes | No | Yes | Yes |
214
+ | API-first approach | Yes | No | Partially | Partially |
@@ -0,0 +1,183 @@
1
+ <div align="center">
2
+ <img src="https://github.com/brilliance-admin/backend-python/blob/main/example/static/logo-outline.png?raw=true"
3
+ alt="Brilliance Admin"
4
+ width="600">
5
+
6
+ [![PyPI](https://img.shields.io/pypi/v/brilliance-admin)](https://pypi.org/project/brilliance-admin/)
7
+ [![CI](https://github.com/brilliance-admin/backend-python/actions/workflows/deploy.yml/badge.svg)](https://github.com/brilliance-admin/backend-python/actions)
8
+
9
+ Simple and lightweight admin panel framework powered by `FastAPI` and `Vue3` `Vuetify` together. \
10
+ Integrated with `SQLAlchemy`. Inspaired by Django Admin and DRF.\
11
+ _Some call it heavenly in its brilliance._
12
+
13
+ ### [Live Demo](https://brilliance-admin.com/) | [Demo Sources](https://github.com/brilliance-admin/backend-python/tree/main/example) | Documentation (todo)
14
+
15
+ <img src="https://github.com/brilliance-admin/backend-python/blob/main/screenshots/websitemockupgenerator.png?raw=true"
16
+ alt="Preview">
17
+
18
+ </div>
19
+
20
+ **Key ideas:**
21
+ - **API oriented**\
22
+ Works entirely on FastAPI and provides a prebuilt SPA [frontend](https://github.com/brilliance-admin/frontend) via static files (Vue3 + Vuetify). No separate startup is required.
23
+ > Data generation/updating API separated from rendering fontend with zero hardcode, this makes it possible to have a single frontend with multiple backend implementations in different languages and makes test coverage easier.
24
+ - **Rich visualization**\
25
+ Providing rich and convenient ways to display and manage data (tables, charts, etc) from any data source.
26
+ - **ORM**\
27
+ Automatic schema generation and methods for CRUD operations.
28
+ - **Minimal boilerplate**\
29
+ Focused on simplified, but rich configuration.
30
+
31
+ **How it works:**
32
+ - After authentication, the user receives the admin panel schema, and the frontend renders it
33
+ - The frontend communicates with the backend via API to fetch and modify data
34
+
35
+ ### Features:
36
+
37
+ * Tables with full CRUD support, including filtering, sorting, and pagination.
38
+ * Ability to define custom table actions with forms, response messages, and file downloads.
39
+ * Graphs via ChartJS
40
+ * Localization support
41
+ * Adapted for different screen sizes and mobile devices
42
+ * Authorization via any account data source
43
+
44
+ **Integrations:**
45
+ * **SQLAlchemy** - schema autogeneration for tables + CRUD operations + authorization
46
+
47
+ **Planned:**
48
+ * Role-based access control system
49
+ * Nested data support for creation and detail views
50
+ * Django ORM inegration
51
+
52
+ ## How to use it
53
+
54
+ Installation:
55
+ ``` shell
56
+ pip install brilliance-admin
57
+ ```
58
+
59
+ You need to generate `AdminSchema` instance:
60
+ ``` python
61
+ from brilliance_admin import schema
62
+
63
+
64
+ class CategoryExample(schema.CategoryTable):
65
+ "Implementation of get_list and retrieve; update and create are optional"
66
+
67
+
68
+ admin_schema = schema.AdminSchema(
69
+ title='Admin Panel',
70
+ auth=YourAdminAuthentication(),
71
+ groups=[
72
+ schema.Group(
73
+ slug='example',
74
+ title='Example',
75
+ icon='mdi-star',
76
+ categories=[
77
+ CategoryExample(),
78
+ ]
79
+ ),
80
+ ],
81
+ )
82
+
83
+ admin_app = admin_schema.generate_app()
84
+
85
+ # Your FastAPI app
86
+ app = FastAPI()
87
+ app.mount('/admin', admin_app)
88
+ ```
89
+
90
+ ## SQLAlchemy integration
91
+
92
+ Supports automatic schema generation for CRUD tables:
93
+
94
+ ``` python
95
+ category = sqlalchemy.SQLAlchemyAdmin(db_async_session=async_sessionmaker, model=Terminal)
96
+ ```
97
+
98
+ > [!NOTE]
99
+ > If `table_schema` is not specified, it will be generated automatically with all discovered fields and relationships
100
+
101
+ Now, the `category` instance can be passed to `categories`.
102
+
103
+ ### DRF class style schema
104
+
105
+ ``` python
106
+ from brilliance_admin import sqlalchemy
107
+ from brilliance_admin.translations import TranslateText as _
108
+
109
+ from your_project.models import Terminal
110
+
111
+
112
+ class TerminalFiltersSchema(sqlalchemy.SQLAlchemyFieldsSchema):
113
+ model = Terminal
114
+ fields = ['id', 'created_at']
115
+ created_at = schema.DateTimeField(range=True)
116
+
117
+
118
+ class TerminalSchema(sqlalchemy.SQLAlchemyFieldsSchema):
119
+ model = Terminal
120
+ list_display = ['id', 'merchant_id']
121
+
122
+
123
+ class TerminalAdmin(sqlalchemy.SQLAlchemyAdmin):
124
+ db_async_session = async_sessionmaker
125
+ model = Terminal
126
+ title = _('terminals')
127
+ icon = 'mdi-console-network-outline'
128
+
129
+ ordering_fields = ['id']
130
+ search_fields = ['id', 'title']
131
+
132
+ table_schema = TerminalSchema()
133
+ table_filters = TerminalFiltersSchema()
134
+
135
+
136
+ category = TerminalAdmin()
137
+ ```
138
+
139
+ ### Can be used both via inheritance and instancing
140
+
141
+ Optionally, functional-style generation can be used to reduce boilerplate code
142
+
143
+ Availiable for `SQLAlchemyAdmin` and `SQLAlchemyFieldsSchema`
144
+
145
+ ``` python
146
+ category = sqlalchemy.SQLAlchemyAdmin(
147
+ db_async_session=async_sessionmaker,
148
+ model=Terminal,
149
+
150
+ table_schema = sqlalchemy.SQLAlchemyFieldsSchema(
151
+ model=Terminal,
152
+ list_display=['id', 'merchant_id'],
153
+ ),
154
+ table_filters = sqlalchemy.SQLAlchemyFieldsSchema(
155
+ model=Terminal,
156
+ fields=['id', 'created_at'],
157
+ created_at=schema.DateTimeField(range=True),
158
+ ),
159
+ )
160
+ ```
161
+
162
+ ### SQLAlchemy JWT Authentication
163
+
164
+ ``` python
165
+ auth = sqlalchemy.SQLAlchemyJWTAdminAuthentication(
166
+ secret='auth_secret',
167
+ db_async_session=async_session,
168
+ user_model=User,
169
+ )
170
+ ```
171
+
172
+ ## Comparison of Similar Projects
173
+
174
+ | Criterion | Brilliance Admin | Django Admin/Unfold | FastAPI Admin | Starlette Admin |
175
+ |---------|------------------|---------------|---------------|-----------------|
176
+ | Base framework | FastAPI | Django | FastAPI | Starlette / FastAPI |
177
+ | Rendering model | Prebuilt Vue 3 + Vuetify SPA + Jinja2 | Server-side Django templates | Server-side Jinja2 templates + Tabler UI | Server-side Jinja2 templates + Tabler UI |
178
+ | Frontend architecture | Separate frontend (SPA) | Classic server-rendered UI | Server-rendered UI with JS interactivity | Server-rendered UI with JS interactivity |
179
+ | Data source | Any source + SQLAlchemy | Django ORM | Tortoise ORM | Any source + SQLAlchemy, MongoDB |
180
+ | Multiple databases per model | Yes | Database routers | No (global engine) | Yes (session per ModelView) |
181
+ | Schema generation | User-defined format | From Django models | From ORM models | User-defined format |
182
+ | Async support | Yes | No | Yes | Yes |
183
+ | API-first approach | Yes | No | Partially | Partially |
@@ -1,4 +1,4 @@
1
1
  # pylint: disable=wildcard-import, unused-wildcard-import, unused-import
2
2
  # flake8: noqa: F405
3
- from admin_panel.integrations import sqlalchemy
4
- from admin_panel import schema
3
+ from brilliance_admin.integrations import sqlalchemy
4
+ from brilliance_admin import schema
@@ -0,0 +1,18 @@
1
+ from fastapi import APIRouter
2
+
3
+ from .views.schema import router as schema_router
4
+ from .views.table import router as schema_table
5
+ from .views.auth import router as schema_auth
6
+ from .views.autocomplete import router as schema_autocomplete
7
+ from .views.graphs import router as schema_graphs
8
+ from .views.settings import router as schema_settings
9
+ from .views.index import router as schema_index
10
+
11
+ brilliance_admin_router = APIRouter()
12
+ brilliance_admin_router.include_router(schema_router)
13
+ brilliance_admin_router.include_router(schema_table)
14
+ brilliance_admin_router.include_router(schema_auth)
15
+ brilliance_admin_router.include_router(schema_autocomplete)
16
+ brilliance_admin_router.include_router(schema_graphs)
17
+ brilliance_admin_router.include_router(schema_settings)
18
+ brilliance_admin_router.include_router(schema_index)
@@ -1,6 +1,6 @@
1
1
  from fastapi import HTTPException
2
2
 
3
- from admin_panel.auth import AdminAuthentication
3
+ from brilliance_admin.auth import AdminAuthentication
4
4
 
5
5
 
6
6
  async def get_user(request):
@@ -1,10 +1,10 @@
1
1
  from fastapi import APIRouter, Request
2
2
  from fastapi.responses import JSONResponse
3
3
 
4
- from admin_panel.auth import AdminAuthentication, AuthData, AuthResult
5
- from admin_panel.exceptions import AdminAPIException, APIError
6
- from admin_panel.schema.admin_schema import AdminSchema
7
- from admin_panel.translations import LanguageManager
4
+ from brilliance_admin.auth import AdminAuthentication, AuthData, AuthResult
5
+ from brilliance_admin.exceptions import AdminAPIException, APIError
6
+ from brilliance_admin.schema.admin_schema import AdminSchema
7
+ from brilliance_admin.translations import LanguageContext
8
8
 
9
9
  router = APIRouter(prefix="/auth", tags=["Auth"])
10
10
 
@@ -17,8 +17,8 @@ async def login(request: Request, auth_data: AuthData) -> AuthResult:
17
17
  schema: AdminSchema = request.app.state.schema
18
18
 
19
19
  language_slug = request.headers.get('Accept-Language')
20
- language_manager: LanguageManager = schema.get_language_manager(language_slug)
21
- context = {'language_manager': language_manager}
20
+ language_context: LanguageContext = schema.get_language_context(language_slug)
21
+ context = {'language_context': language_context}
22
22
 
23
23
  auth: AdminAuthentication = schema.auth
24
24
  try:
@@ -1,12 +1,12 @@
1
1
  from fastapi import APIRouter, Request
2
2
  from fastapi.responses import JSONResponse
3
3
 
4
- from admin_panel.api.utils import get_category
5
- from admin_panel.exceptions import AdminAPIException
6
- from admin_panel.schema.admin_schema import AdminSchema
7
- from admin_panel.schema.table.table_models import AutocompleteData, AutocompleteResult
8
- from admin_panel.translations import LanguageManager
9
- from admin_panel.utils import get_logger
4
+ from brilliance_admin.api.utils import get_category
5
+ from brilliance_admin.exceptions import AdminAPIException
6
+ from brilliance_admin.schema.admin_schema import AdminSchema
7
+ from brilliance_admin.schema.table.table_models import AutocompleteData, AutocompleteResult
8
+ from brilliance_admin.translations import LanguageContext
9
+ from brilliance_admin.utils import get_logger
10
10
 
11
11
  router = APIRouter(prefix="/autocomplete", tags=["Autocomplete"])
12
12
 
@@ -19,11 +19,11 @@ async def autocomplete(request: Request, group: str, category: str, data: Autoco
19
19
  schema_category, user = await get_category(request, group, category)
20
20
 
21
21
  language_slug = request.headers.get('Accept-Language')
22
- language_manager: LanguageManager = schema.get_language_manager(language_slug)
23
- context = {'language_manager': language_manager}
22
+ language_context: LanguageContext = schema.get_language_context(language_slug)
23
+ context = {'language_context': language_context}
24
24
 
25
25
  try:
26
- result: AutocompleteResult = await schema_category.autocomplete(data, user, language_manager)
26
+ result: AutocompleteResult = await schema_category.autocomplete(data, user, language_context)
27
27
  except AdminAPIException as e:
28
28
  return JSONResponse(e.get_error().model_dump(mode='json', context=context), status_code=e.status_code)
29
29
  except Exception as e:
@@ -1,12 +1,12 @@
1
1
  from fastapi import APIRouter, Request
2
2
  from fastapi.responses import JSONResponse
3
3
 
4
- from admin_panel.api.utils import get_category
5
- from admin_panel.exceptions import AdminAPIException
6
- from admin_panel.schema.admin_schema import AdminSchema
7
- from admin_panel.schema.graphs.category_graphs import CategoryGraphs, GraphData, GraphsDataResult
8
- from admin_panel.translations import LanguageManager
9
- from admin_panel.utils import get_logger
4
+ from brilliance_admin.api.utils import get_category
5
+ from brilliance_admin.exceptions import AdminAPIException
6
+ from brilliance_admin.schema.admin_schema import AdminSchema
7
+ from brilliance_admin.schema.graphs.category_graphs import CategoryGraphs, GraphData, GraphsDataResult
8
+ from brilliance_admin.translations import LanguageContext
9
+ from brilliance_admin.utils import get_logger
10
10
 
11
11
  router = APIRouter(prefix="/graph", tags=["Category - Graph"])
12
12
 
@@ -21,8 +21,8 @@ async def graph_data(request: Request, group: str, category: str, data: GraphDat
21
21
  result: GraphsDataResult = await schema_category.get_data(data, user)
22
22
 
23
23
  language_slug = request.headers.get('Accept-Language')
24
- language_manager: LanguageManager = schema.get_language_manager(language_slug)
25
- context = {'language_manager': language_manager}
24
+ language_context: LanguageContext = schema.get_language_context(language_slug)
25
+ context = {'language_context': language_context}
26
26
 
27
27
  try:
28
28
  return JSONResponse(result.model_dump(mode='json', context=context))
@@ -1,15 +1,17 @@
1
+ from pathlib import PurePosixPath
2
+
1
3
  from fastapi import APIRouter, HTTPException, Request
2
4
  from fastapi.responses import HTMLResponse
3
5
  from fastapi.templating import Jinja2Templates
4
6
  from jinja2 import Environment, PackageLoader, select_autoescape
5
7
 
6
- from admin_panel.schema import AdminSchema
8
+ from brilliance_admin.schema import AdminSchema
7
9
 
8
10
  router = APIRouter()
9
11
 
10
12
  templates = Jinja2Templates(
11
13
  env=Environment(
12
- loader=PackageLoader("admin_panel", "templates"),
14
+ loader=PackageLoader("brilliance_admin", "templates"),
13
15
  autoescape=select_autoescape(["html", "xml"]),
14
16
  )
15
17
  )
@@ -25,8 +27,13 @@ async def admin_index(request: Request, rest_of_path: str):
25
27
  The request responds with a pre-rendered SPA served as an HTML page.
26
28
  '''
27
29
 
28
- path = "/" + rest_of_path
29
- if path in EXACT_BLOCK or path.startswith(PREFIX_BLOCK):
30
+ path = PurePosixPath('/' + rest_of_path)
31
+
32
+ if '..' in path.parts:
33
+ raise HTTPException(status_code=404)
34
+
35
+ path_str = str(path)
36
+ if path_str in EXACT_BLOCK or path_str.startswith(PREFIX_BLOCK):
30
37
  raise HTTPException(status_code=404)
31
38
 
32
39
  schema: AdminSchema = request.app.state.schema
@@ -1,9 +1,9 @@
1
1
  from fastapi import APIRouter, Request
2
2
  from fastapi.responses import JSONResponse
3
3
 
4
- from admin_panel.auth import AdminAuthentication
5
- from admin_panel.exceptions import AdminAPIException, APIError
6
- from admin_panel.schema import AdminSchema, AdminSchemaData
4
+ from brilliance_admin.auth import AdminAuthentication
5
+ from brilliance_admin.exceptions import AdminAPIException, APIError
6
+ from brilliance_admin.schema import AdminSchema, AdminSchemaData
7
7
 
8
8
  router = APIRouter(prefix="/schema", tags=["Main admin schema"])
9
9
 
@@ -1,9 +1,9 @@
1
1
  from fastapi import APIRouter, Request
2
2
  from fastapi.responses import JSONResponse
3
3
 
4
- from admin_panel.exceptions import AdminAPIException, APIError
5
- from admin_panel.schema.admin_schema import AdminSchema, AdminSettingsData
6
- from admin_panel.translations import LanguageManager
4
+ from brilliance_admin.exceptions import AdminAPIException, APIError
5
+ from brilliance_admin.schema.admin_schema import AdminSchema, AdminSettingsData
6
+ from brilliance_admin.translations import LanguageContext
7
7
 
8
8
  router = APIRouter(tags=["Settings"])
9
9
 
@@ -19,8 +19,8 @@ async def get_settings(request: Request) -> AdminSettingsData:
19
19
  schema: AdminSchema = request.app.state.schema
20
20
 
21
21
  language_slug = request.headers.get('Accept-Language')
22
- language_manager: LanguageManager = schema.get_language_manager(language_slug)
23
- context = {'language_manager': language_manager}
22
+ language_context: LanguageContext = schema.get_language_context(language_slug)
23
+ context = {'language_context': language_context}
24
24
 
25
25
  try:
26
26
  admin_settings = await schema.get_settings(request)