fastadmin 0.1.15__tar.gz → 0.1.17__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 (31) hide show
  1. {fastadmin-0.1.15 → fastadmin-0.1.17}/PKG-INFO +11 -110
  2. {fastadmin-0.1.15 → fastadmin-0.1.17}/README.md +10 -109
  3. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/api/api.py +3 -5
  4. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/models/base.py +13 -10
  5. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/models/orm/tortoise.py +1 -1
  6. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/schemas/configuration.py +1 -0
  7. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/static/js/main.min.js +3 -3
  8. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/static/js/main.min.js.map +1 -1
  9. {fastadmin-0.1.15 → fastadmin-0.1.17}/pyproject.toml +1 -1
  10. {fastadmin-0.1.15 → fastadmin-0.1.17}/LICENSE +0 -0
  11. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/__init__.py +0 -0
  12. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/api/__init__.py +0 -0
  13. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/api/depends.py +0 -0
  14. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/api/helpers.py +0 -0
  15. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/app.py +0 -0
  16. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/models/__init__.py +0 -0
  17. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/models/decorators.py +0 -0
  18. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/models/helpers.py +0 -0
  19. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/models/orm/__init__.py +0 -0
  20. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/schemas/__init__.py +0 -0
  21. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/schemas/api.py +0 -0
  22. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/settings.py +0 -0
  23. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/static/css/main.min.css +0 -0
  24. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/static/css/main.min.css.map +0 -0
  25. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/static/images/favicon.png +0 -0
  26. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/static/images/header-logo.svg +0 -0
  27. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/static/images/sign-in-logo.svg +0 -0
  28. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/static/js/787.cda612ba.chunk.js +0 -0
  29. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/static/js/787.cda612ba.chunk.js.map +0 -0
  30. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/templates/index.html +0 -0
  31. {fastadmin-0.1.15 → fastadmin-0.1.17}/fastadmin/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastadmin
3
- Version: 0.1.15
3
+ Version: 0.1.17
4
4
  Summary:
5
5
  Home-page: https://github.com/vsdudakov/fastadmin
6
6
  License: MIT
@@ -39,6 +39,12 @@ Description-Content-Type: text/markdown
39
39
  ![List View](https://raw.githubusercontent.com/vsdudakov/fastadmin/main/docs/images/list.png)
40
40
  ![Change View](https://raw.githubusercontent.com/vsdudakov/fastadmin/main/docs/images/change.png)
41
41
 
42
+ <p align="center">
43
+ <a href="https://twitter.com/intent/tweet?text=Admin%20Dashboard%20For%20FastAPI&url=https://github.com/vsdudakov/fastadmin&hashtags=FastAPI,AdminDashboard">
44
+ <img alt="tweet" src="https://img.shields.io/twitter/url/https/twitter?label=Share%20on%20twitter&style=social" target="_blank" />
45
+ </a>
46
+ </p>
47
+
42
48
  ## Introduction
43
49
 
44
50
  FastAdmin is an easy-to-use Admin App for FastAPI inspired by Django Admin.
@@ -158,122 +164,17 @@ class GroupAdmin(TortoiseModelAdmin):
158
164
 
159
165
  #### Run your project
160
166
 
161
- Run your project (see https://fastapi.tiangolo.com/tutorial/first-steps/):
167
+ Run your project (see [https://fastapi.tiangolo.com/tutorial/first-steps/](https://fastapi.tiangolo.com/tutorial/first-steps/)):
162
168
 
163
169
  ```bash
164
170
  uvicorn ...
165
171
  ```
166
172
 
167
- Go to http://localhost:8000/admin
168
-
169
- ## Configuration
170
-
171
- You can find all env variables to configure FastAdmin [here](https://github.com/vsdudakov/fastadmin/blob/main/fastadmin/settings.py)
172
-
173
- You can find all parameters and methods to configure your ModelAdmin classes [here](https://github.com/vsdudakov/fastadmin/blob/main/fastadmin/models/base.py)
174
-
175
- Example:
176
-
177
- ```python
178
- from fastadmin import TortoiseModelAdmin, register, action, display
179
-
180
- @register(User)
181
- class UserAdmin(TortoiseModelAdmin):
182
- label_fields = ("email", "id")
183
- exclude = ("hash_password",)
184
- list_display = ("id", "email", "has_hash_password", "is_superuser", "is_active")
185
- list_display_links = ("id",)
186
- list_filter = ("id", "email", "is_superuser")
187
- search_fields = ("email",)
188
- actions = ("set_as_active",)
173
+ Go to [http://localhost:8000/admin](http://localhost:8000/admin).
189
174
 
190
- def has_delete_permission(self) -> bool:
191
- return False
175
+ ## Documentation
192
176
 
193
- @action(description="Set as active")
194
- async def set_as_active(self, ids: list[int | UUID]) -> None:
195
- await User.filter(id__in=ids).update(is_active=True)
196
-
197
- @display
198
- async def has_hash_password(self, obj: Any) -> Any:
199
- return obj.hash_password is not None
200
-
201
- ...
202
- ```
203
-
204
- ## Other ORMs or own implementation
205
-
206
- We are going to support SQLAlchemy and Pony ORM soon...
207
-
208
- If you have smth else (your own implementation of ORM and so on) you will may overload ModelAdmin class and implement the following interfaces
209
-
210
- ```python
211
- from typing import Any
212
- from collections import OrderedDict
213
- from fastadmin import ModelAdmin, WidgetType
214
-
215
- class MyModelAdmin(ModelAdmin):
216
- async def save_model(self, id: UUID | int | None, payload: dict) -> dict | None:
217
- """This method is used to save orm/db model object.
218
-
219
- :params id: an id of object.
220
- :params payload: a payload from request.
221
- :return: A saved object or None.
222
- """
223
- raise NotImplementedError
224
-
225
- async def delete_model(self, id: UUID | int) -> None:
226
- """This method is used to delete orm/db model object.
227
-
228
- :params id: an id of object.
229
- :return: None.
230
- """
231
- raise NotImplementedError
232
-
233
- async def get_obj(self, id: UUID | int) -> dict | None:
234
- """This method is used to get orm/db model object by id.
235
-
236
- :params id: an id of object.
237
- :return: An object or None.
238
- """
239
- raise NotImplementedError
240
-
241
- async def get_list(
242
- self,
243
- offset: int | None = None,
244
- limit: int | None = None,
245
- search: str | None = None,
246
- sort_by: str | None = None,
247
- filters: dict | None = None,
248
- ) -> tuple[list[dict], int]:
249
- """This method is used to get list of orm/db model objects.
250
-
251
- :params offset: an offset for pagination.
252
- :params limit: a limit for pagination.
253
- :params search: a search query.
254
- :params sort_by: a sort by field name.
255
- :params filters: a dict of filters.
256
- :return: A tuple of list of objects and total count.
257
- """
258
- raise NotImplementedError
259
-
260
- def get_model_fields(self) -> OrderedDict[str, dict]:
261
- """This method is used to get all orm/db model fields
262
- with saving ordering (non relations, fk, o2o, m2m).
263
-
264
- :return: An OrderedDict of model fields.
265
- """
266
- raise NotImplementedError
267
-
268
- def get_form_widget(self, field_name: str) -> tuple[WidgetType, dict]:
269
- """This method is used to get form item widget
270
- for field from orm/db model.
271
-
272
- :params field_name: a model field name.
273
- :return: A tuple of widget type and widget props.
274
- """
275
- raise NotImplementedError
276
- ```
177
+ See full documentation [here](https://vsdudakov.github.io/fastadmin/).
277
178
 
278
179
  ## License
279
180
 
@@ -12,6 +12,12 @@
12
12
  ![List View](https://raw.githubusercontent.com/vsdudakov/fastadmin/main/docs/images/list.png)
13
13
  ![Change View](https://raw.githubusercontent.com/vsdudakov/fastadmin/main/docs/images/change.png)
14
14
 
15
+ <p align="center">
16
+ <a href="https://twitter.com/intent/tweet?text=Admin%20Dashboard%20For%20FastAPI&url=https://github.com/vsdudakov/fastadmin&hashtags=FastAPI,AdminDashboard">
17
+ <img alt="tweet" src="https://img.shields.io/twitter/url/https/twitter?label=Share%20on%20twitter&style=social" target="_blank" />
18
+ </a>
19
+ </p>
20
+
15
21
  ## Introduction
16
22
 
17
23
  FastAdmin is an easy-to-use Admin App for FastAPI inspired by Django Admin.
@@ -131,122 +137,17 @@ class GroupAdmin(TortoiseModelAdmin):
131
137
 
132
138
  #### Run your project
133
139
 
134
- Run your project (see https://fastapi.tiangolo.com/tutorial/first-steps/):
140
+ Run your project (see [https://fastapi.tiangolo.com/tutorial/first-steps/](https://fastapi.tiangolo.com/tutorial/first-steps/)):
135
141
 
136
142
  ```bash
137
143
  uvicorn ...
138
144
  ```
139
145
 
140
- Go to http://localhost:8000/admin
141
-
142
- ## Configuration
143
-
144
- You can find all env variables to configure FastAdmin [here](https://github.com/vsdudakov/fastadmin/blob/main/fastadmin/settings.py)
145
-
146
- You can find all parameters and methods to configure your ModelAdmin classes [here](https://github.com/vsdudakov/fastadmin/blob/main/fastadmin/models/base.py)
147
-
148
- Example:
149
-
150
- ```python
151
- from fastadmin import TortoiseModelAdmin, register, action, display
152
-
153
- @register(User)
154
- class UserAdmin(TortoiseModelAdmin):
155
- label_fields = ("email", "id")
156
- exclude = ("hash_password",)
157
- list_display = ("id", "email", "has_hash_password", "is_superuser", "is_active")
158
- list_display_links = ("id",)
159
- list_filter = ("id", "email", "is_superuser")
160
- search_fields = ("email",)
161
- actions = ("set_as_active",)
146
+ Go to [http://localhost:8000/admin](http://localhost:8000/admin).
162
147
 
163
- def has_delete_permission(self) -> bool:
164
- return False
148
+ ## Documentation
165
149
 
166
- @action(description="Set as active")
167
- async def set_as_active(self, ids: list[int | UUID]) -> None:
168
- await User.filter(id__in=ids).update(is_active=True)
169
-
170
- @display
171
- async def has_hash_password(self, obj: Any) -> Any:
172
- return obj.hash_password is not None
173
-
174
- ...
175
- ```
176
-
177
- ## Other ORMs or own implementation
178
-
179
- We are going to support SQLAlchemy and Pony ORM soon...
180
-
181
- If you have smth else (your own implementation of ORM and so on) you will may overload ModelAdmin class and implement the following interfaces
182
-
183
- ```python
184
- from typing import Any
185
- from collections import OrderedDict
186
- from fastadmin import ModelAdmin, WidgetType
187
-
188
- class MyModelAdmin(ModelAdmin):
189
- async def save_model(self, id: UUID | int | None, payload: dict) -> dict | None:
190
- """This method is used to save orm/db model object.
191
-
192
- :params id: an id of object.
193
- :params payload: a payload from request.
194
- :return: A saved object or None.
195
- """
196
- raise NotImplementedError
197
-
198
- async def delete_model(self, id: UUID | int) -> None:
199
- """This method is used to delete orm/db model object.
200
-
201
- :params id: an id of object.
202
- :return: None.
203
- """
204
- raise NotImplementedError
205
-
206
- async def get_obj(self, id: UUID | int) -> dict | None:
207
- """This method is used to get orm/db model object by id.
208
-
209
- :params id: an id of object.
210
- :return: An object or None.
211
- """
212
- raise NotImplementedError
213
-
214
- async def get_list(
215
- self,
216
- offset: int | None = None,
217
- limit: int | None = None,
218
- search: str | None = None,
219
- sort_by: str | None = None,
220
- filters: dict | None = None,
221
- ) -> tuple[list[dict], int]:
222
- """This method is used to get list of orm/db model objects.
223
-
224
- :params offset: an offset for pagination.
225
- :params limit: a limit for pagination.
226
- :params search: a search query.
227
- :params sort_by: a sort by field name.
228
- :params filters: a dict of filters.
229
- :return: A tuple of list of objects and total count.
230
- """
231
- raise NotImplementedError
232
-
233
- def get_model_fields(self) -> OrderedDict[str, dict]:
234
- """This method is used to get all orm/db model fields
235
- with saving ordering (non relations, fk, o2o, m2m).
236
-
237
- :return: An OrderedDict of model fields.
238
- """
239
- raise NotImplementedError
240
-
241
- def get_form_widget(self, field_name: str) -> tuple[WidgetType, dict]:
242
- """This method is used to get form item widget
243
- for field from orm/db model.
244
-
245
- :params field_name: a model field name.
246
- :return: A tuple of widget type and widget props.
247
- """
248
- raise NotImplementedError
249
- ```
150
+ See full documentation [here](https://vsdudakov.github.io/fastadmin/).
250
151
 
251
152
  ## License
252
153
 
@@ -370,7 +370,7 @@ async def configuration(
370
370
  ),
371
371
  )
372
372
 
373
- for field_name in admin_obj.list_display:
373
+ for column_index, field_name in enumerate(admin_obj.list_display):
374
374
  display_field_function = getattr(admin_obj, field_name, None)
375
375
  if (
376
376
  not display_field_function
@@ -379,15 +379,12 @@ async def configuration(
379
379
  ):
380
380
  continue
381
381
 
382
- column_index = admin_obj.list_display.index(field_name) if field_name in admin_obj.list_display else None
383
- if column_index is None:
384
- continue
385
382
  fields_schema.append(
386
383
  ModelFieldSchema(
387
384
  name=field_name,
388
385
  list_configuration=ListConfigurationFieldSchema(
389
386
  index=column_index,
390
- sorter=None,
387
+ sorter=False,
391
388
  is_link=field_name in admin_obj.list_display_links,
392
389
  empty_value_display=admin_obj.empty_value_display,
393
390
  filter_widget_type=None,
@@ -433,6 +430,7 @@ async def configuration(
433
430
  actions_on_bottom=admin_obj.actions_on_bottom,
434
431
  actions_selection_counter=admin_obj.actions_selection_counter,
435
432
  fields=fields_schema,
433
+ fieldsets=admin_obj.fieldsets,
436
434
  list_per_page=admin_obj.list_per_page,
437
435
  save_on_top=admin_obj.save_on_top,
438
436
  save_as=admin_obj.save_as,
@@ -420,18 +420,21 @@ class BaseModelAdmin:
420
420
 
421
421
  :return: A list of model field names.
422
422
  """
423
- fields = self.fields
424
423
  model_fields = self.get_model_fields()
425
- if not fields:
426
- return [f for f in model_fields if not self.exclude or f not in self.exclude]
427
- return [f for f in fields if f in model_fields]
428
424
 
429
- # def get_fieldsets(self) -> Sequence[tuple[str | None, dict[str, Sequence[str]]]]:
430
- # """This method is used to get fieldsets data for form view.
431
-
432
- # :return: A list of fieldsets data.
433
- # """
434
- # return self.fieldsets
425
+ fields = [f for f in model_fields if model_fields[f].get("is_pk")]
426
+ if not self.fields:
427
+ if self.fieldsets:
428
+ for item in self.fieldsets:
429
+ for field in item[1].get("fields") or []:
430
+ if field not in fields and field not in self.exclude:
431
+ fields.append(field)
432
+ else:
433
+ for field in model_fields:
434
+ if field not in fields and field not in self.exclude:
435
+ fields.append(field)
436
+
437
+ return fields
435
438
 
436
439
  def has_add_permission(self) -> bool:
437
440
  """This method is used to check if user has permission to add new model instance.
@@ -247,7 +247,7 @@ class TortoiseModelAdmin(BaseModelAdmin):
247
247
  widget_props = {
248
248
  "required": field.get("required") or False,
249
249
  "disabled": field_name in self.readonly_fields,
250
- "readonly": field_name in self.readonly_fields,
250
+ "readOnly": field_name in self.readonly_fields,
251
251
  }
252
252
  match field.get("orm_class_name"):
253
253
  case "CharField":
@@ -92,6 +92,7 @@ class ModelSchema(BaseModel):
92
92
  actions_on_bottom: bool | None
93
93
  actions_selection_counter: bool | None
94
94
  fields: Sequence[ModelFieldSchema]
95
+ fieldsets: Sequence[tuple[str | None, dict[str, Sequence[str]]]] | None
95
96
  list_per_page: int | None
96
97
  save_on_top: bool | None
97
98
  save_as: bool | None