├── main.py
├── tests
├── __init__.py
├── test_utils
│ ├── __init__.py
│ └── test_file_upload.py
├── data
│ ├── locales
│ │ ├── messages.pot
│ │ ├── en
│ │ │ └── LC_MESSAGES
│ │ │ │ ├── messages.po
│ │ │ │ └── messages.mo
│ │ └── uk
│ │ │ └── LC_MESSAGES
│ │ │ ├── messages.po
│ │ │ └── messages.mo
│ └── extra_locales
│ │ └── uk
│ │ └── LC_MESSAGES
│ │ ├── messages.po
│ │ └── messages.mo
├── conftest.py
└── test_i18n.py
├── examples
└── __init__.py
├── fastapi_admin2
├── ui
│ ├── __init__.py
│ ├── resources
│ │ ├── base.py
│ │ ├── link.py
│ │ ├── dropdown.py
│ │ ├── __init__.py
│ │ ├── action.py
│ │ └── column.py
│ └── widgets
│ │ ├── exceptions.py
│ │ ├── __init__.py
│ │ ├── displays.py
│ │ ├── filters.py
│ │ └── inputs.py
├── utils
│ ├── __init__.py
│ ├── files
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── utils.py
│ │ ├── static.py
│ │ ├── s3.py
│ │ └── on_premise.py
│ ├── depends.py
│ ├── forms.py
│ ├── responses.py
│ └── templating.py
├── backends
│ ├── __init__.py
│ ├── sqla
│ │ ├── dao
│ │ │ ├── __init__.py
│ │ │ └── admin_dao.py
│ │ ├── widgets
│ │ │ ├── __init__.py
│ │ │ └── inputs.py
│ │ ├── markers.py
│ │ ├── __init__.py
│ │ ├── models.py
│ │ ├── queriers.py
│ │ ├── field_converters.py
│ │ ├── filters.py
│ │ ├── model_resource.py
│ │ └── toolings.py
│ └── tortoise
│ │ ├── dao
│ │ ├── __init__.py
│ │ └── admin_dao.py
│ │ ├── widgets
│ │ ├── __init__.py
│ │ └── inputs.py
│ │ ├── models.py
│ │ ├── queriers.py
│ │ ├── __init__.py
│ │ ├── filters.py
│ │ ├── field_converters.py
│ │ └── model_resource.py
├── middlewares
│ ├── __init__.py
│ ├── i18n
│ │ ├── __init__.py
│ │ ├── impl.py
│ │ └── base.py
│ ├── theme.py
│ └── templating.py
├── controllers
│ ├── __init__.py
│ ├── dependencies.py
│ └── resources.py
├── providers
│ ├── security
│ │ ├── password_hashing
│ │ │ ├── __init__.py
│ │ │ ├── protocol.py
│ │ │ └── argon2_cffi.py
│ │ ├── __init__.py
│ │ ├── responses.py
│ │ ├── dependencies.py
│ │ ├── dto.py
│ │ └── provider.py
│ └── __init__.py
├── i18n
│ ├── exceptions.py
│ ├── __init__.py
│ ├── locales
│ │ ├── en
│ │ │ └── LC_MESSAGES
│ │ │ │ ├── messages.mo
│ │ │ │ └── messages.po
│ │ ├── ru
│ │ │ └── LC_MESSAGES
│ │ │ │ ├── messages.mo
│ │ │ │ └── messages.po
│ │ └── zh
│ │ │ └── LC_MESSAGES
│ │ │ ├── messages.mo
│ │ │ └── messages.po
│ ├── utils.py
│ ├── lazy_proxy.py
│ └── localizer.py
├── templates
│ ├── widgets
│ │ ├── displays
│ │ │ ├── image.html
│ │ │ ├── boolean.html
│ │ │ └── json.html
│ │ ├── filters
│ │ │ ├── search.html
│ │ │ ├── select.html
│ │ │ └── datetime.html
│ │ └── inputs
│ │ │ ├── input.html
│ │ │ ├── color.html
│ │ │ ├── textarea.html
│ │ │ ├── switch.html
│ │ │ ├── image.html
│ │ │ ├── radio.html
│ │ │ ├── select.html
│ │ │ ├── json.html
│ │ │ ├── many_to_many.html
│ │ │ ├── editor.html
│ │ │ └── datetime.html
│ ├── components
│ │ ├── dropdown-show.html
│ │ ├── alert_error.html
│ │ ├── link.html
│ │ ├── model.html
│ │ ├── language.html
│ │ ├── mode_switch.html
│ │ ├── select.html
│ │ └── dropdown.html
│ ├── errors
│ │ ├── maintenance.html
│ │ ├── 403.html
│ │ ├── 401.html
│ │ ├── 500.html
│ │ └── 404.html
│ ├── providers
│ │ └── login
│ │ │ ├── avatar.html
│ │ │ ├── renew_password.html
│ │ │ └── login.html
│ ├── create.html
│ ├── update.html
│ ├── base.html
│ ├── init.html
│ └── layout.html
├── __init__.py
├── enums.py
├── entities.py
├── default_settings.py
├── exceptions.py
├── depends.py
└── app.py
├── docs
└── _static
│ ├── example.png
│ └── dark_mode.png
├── babel.cfg
├── pyproject.toml
├── README.md
└── .gitignore
/main.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/test_utils/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fastapi_admin2/ui/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fastapi_admin2/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fastapi_admin2/backends/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fastapi_admin2/middlewares/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fastapi_admin2/controllers/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/fastapi_admin2/middlewares/i18n/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fastapi_admin2/backends/sqla/dao/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fastapi_admin2/backends/sqla/widgets/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fastapi_admin2/backends/tortoise/dao/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fastapi_admin2/backends/tortoise/widgets/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/fastapi_admin2/providers/security/password_hashing/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/data/locales/messages.pot:
--------------------------------------------------------------------------------
1 | msgid "test"
2 | msgstr ""
3 |
--------------------------------------------------------------------------------
/tests/data/locales/en/LC_MESSAGES/messages.po:
--------------------------------------------------------------------------------
1 | msgid "test"
2 | msgstr ""
3 |
--------------------------------------------------------------------------------
/tests/data/locales/uk/LC_MESSAGES/messages.po:
--------------------------------------------------------------------------------
1 | msgid "test"
2 | msgstr "тест"
3 |
--------------------------------------------------------------------------------
/tests/data/extra_locales/uk/LC_MESSAGES/messages.po:
--------------------------------------------------------------------------------
1 | msgid "test"
2 | msgstr "тест"
3 |
--------------------------------------------------------------------------------
/fastapi_admin2/ui/resources/base.py:
--------------------------------------------------------------------------------
1 | class Resource:
2 | label: str
3 | icon: str = ""
4 |
--------------------------------------------------------------------------------
/fastapi_admin2/ui/widgets/exceptions.py:
--------------------------------------------------------------------------------
1 | class FilterValidationError(Exception):
2 | pass
3 |
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 | DATA_DIR = Path(__file__).parent / "data"
4 |
--------------------------------------------------------------------------------
/docs/_static/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GLEF1X/fastapi-admin2/HEAD/docs/_static/example.png
--------------------------------------------------------------------------------
/fastapi_admin2/i18n/exceptions.py:
--------------------------------------------------------------------------------
1 | class UnableToExtractLocaleFromRequestError(Exception):
2 | pass
3 |
--------------------------------------------------------------------------------
/docs/_static/dark_mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GLEF1X/fastapi-admin2/HEAD/docs/_static/dark_mode.png
--------------------------------------------------------------------------------
/fastapi_admin2/i18n/__init__.py:
--------------------------------------------------------------------------------
1 | from .localizer import Localizer, I18NLocalizer
2 |
3 | __all__ = ('Localizer', 'I18NLocalizer')
4 |
--------------------------------------------------------------------------------
/fastapi_admin2/providers/security/__init__.py:
--------------------------------------------------------------------------------
1 | from .provider import SecurityProvider
2 |
3 | __all__ = ('SecurityProvider',)
4 |
--------------------------------------------------------------------------------
/fastapi_admin2/templates/widgets/displays/image.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/babel.cfg:
--------------------------------------------------------------------------------
1 | [python: fastapi_admin/**.py]
2 | [jinja2: fastapi_admin/templates/**.html]
3 | extensions = jinja2.ext.i18n,jinja2.ext.autoescape
4 |
--------------------------------------------------------------------------------
/fastapi_admin2/__init__.py:
--------------------------------------------------------------------------------
1 | from .app import FastAPIAdmin
2 |
3 | __version__ = "0.0.1a1"
4 |
5 | __all__ = ('FastAPIAdmin', '__version__')
6 |
--------------------------------------------------------------------------------
/tests/data/locales/en/LC_MESSAGES/messages.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GLEF1X/fastapi-admin2/HEAD/tests/data/locales/en/LC_MESSAGES/messages.mo
--------------------------------------------------------------------------------
/tests/data/locales/uk/LC_MESSAGES/messages.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GLEF1X/fastapi-admin2/HEAD/tests/data/locales/uk/LC_MESSAGES/messages.mo
--------------------------------------------------------------------------------
/tests/data/extra_locales/uk/LC_MESSAGES/messages.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GLEF1X/fastapi-admin2/HEAD/tests/data/extra_locales/uk/LC_MESSAGES/messages.mo
--------------------------------------------------------------------------------
/fastapi_admin2/i18n/locales/en/LC_MESSAGES/messages.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GLEF1X/fastapi-admin2/HEAD/fastapi_admin2/i18n/locales/en/LC_MESSAGES/messages.mo
--------------------------------------------------------------------------------
/fastapi_admin2/i18n/locales/ru/LC_MESSAGES/messages.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GLEF1X/fastapi-admin2/HEAD/fastapi_admin2/i18n/locales/ru/LC_MESSAGES/messages.mo
--------------------------------------------------------------------------------
/fastapi_admin2/i18n/locales/zh/LC_MESSAGES/messages.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GLEF1X/fastapi-admin2/HEAD/fastapi_admin2/i18n/locales/zh/LC_MESSAGES/messages.mo
--------------------------------------------------------------------------------
/fastapi_admin2/ui/resources/link.py:
--------------------------------------------------------------------------------
1 | from fastapi_admin2.ui.resources.base import Resource
2 |
3 |
4 | class Link(Resource):
5 | url: str
6 | target: str = "_self"
7 |
--------------------------------------------------------------------------------
/fastapi_admin2/templates/widgets/displays/boolean.html:
--------------------------------------------------------------------------------
1 | {% if value %}
2 | true
3 | {% else %}
4 | false
5 | {% endif %}
6 |
--------------------------------------------------------------------------------
/fastapi_admin2/ui/resources/dropdown.py:
--------------------------------------------------------------------------------
1 | from typing import List, Type
2 |
3 | from fastapi_admin2.ui.resources.base import Resource
4 |
5 |
6 | class Dropdown(Resource):
7 | resources: List[Type[Resource]]
8 |
--------------------------------------------------------------------------------
/fastapi_admin2/backends/sqla/widgets/inputs.py:
--------------------------------------------------------------------------------
1 | from fastapi_admin2.widgets.inputs import BaseForeignKeyInput
2 |
3 |
4 | class ForeignKey(BaseForeignKeyInput):
5 | async def get_options(self):
6 | pass
7 |
--------------------------------------------------------------------------------
/fastapi_admin2/templates/widgets/filters/search.html:
--------------------------------------------------------------------------------
1 |
{{ value }}
5 |
--------------------------------------------------------------------------------
/fastapi_admin2/utils/files/base.py:
--------------------------------------------------------------------------------
1 | import abc
2 | import os
3 | from typing import NewType, Union
4 |
5 | from starlette.datastructures import UploadFile
6 |
7 | Link = NewType("Link", str)
8 |
9 |
10 | class FileManager(abc.ABC):
11 |
12 | @abc.abstractmethod
13 | async def download_file(self, file: UploadFile) -> Union[Link, os.PathLike]:
14 | pass
15 |
--------------------------------------------------------------------------------
/fastapi_admin2/controllers/dependencies.py:
--------------------------------------------------------------------------------
1 | from fastapi_admin2.entities import ResourceList
2 | from fastapi_admin2.utils.depends import DependencyMarker
3 |
4 |
5 | class ModelListDependencyMarker(DependencyMarker[ResourceList]):
6 | pass
7 |
8 |
9 | class DeleteOneDependencyMarker(DependencyMarker[None]):
10 | pass
11 |
12 |
13 | class DeleteManyDependencyMarker(DependencyMarker[None]):
14 | pass
15 |
--------------------------------------------------------------------------------
/fastapi_admin2/utils/files/utils.py:
--------------------------------------------------------------------------------
1 | import pathlib
2 | from datetime import datetime
3 |
4 | from fastapi import UploadFile
5 |
6 |
7 | def create_unique_file_identifier(file: UploadFile, *parts: str) -> str:
8 | file_extension = pathlib.Path(file.filename).suffix
9 | current_timestamp = str(datetime.now().timestamp()).replace('.', '')
10 | return ''.join(parts) + current_timestamp + file_extension
11 |
--------------------------------------------------------------------------------
/fastapi_admin2/backends/tortoise/models.py:
--------------------------------------------------------------------------------
1 | from tortoise import fields, Model
2 |
3 | from fastapi_admin2.entities import AbstractAdmin
4 |
5 |
6 | class AbstractAdminModel(Model, AbstractAdmin):
7 | id = fields.IntField(pk=True)
8 | username = fields.CharField(max_length=50, unique=True)
9 | password = fields.CharField(max_length=200)
10 | profile_pic = fields.CharField(max_length=100)
11 |
12 | class Meta:
13 | abstract = True
14 |
--------------------------------------------------------------------------------
/fastapi_admin2/providers/__init__.py:
--------------------------------------------------------------------------------
1 | import typing
2 |
3 | from fastapi_admin2.utils.templating import JinjaTemplates
4 |
5 | if typing.TYPE_CHECKING:
6 | from fastapi_admin2.app import FastAPIAdmin
7 |
8 |
9 | class Provider:
10 | name = "provider"
11 | templates: typing.Optional[JinjaTemplates] = None
12 |
13 | def register(self, app: "FastAPIAdmin"):
14 | setattr(app, self.name, self)
15 |
16 | self.templates = app.templates
17 |
--------------------------------------------------------------------------------
/fastapi_admin2/ui/resources/__init__.py:
--------------------------------------------------------------------------------
1 | from .action import ToolbarAction, Action
2 | from .dropdown import Dropdown
3 | from .column import Field, ComputedField
4 | from .link import Link
5 | from .model import AbstractModelResource
6 | from .base import Resource
7 |
8 | __all__ = (
9 | 'ToolbarAction',
10 | 'Action',
11 | 'Resource',
12 | 'Dropdown',
13 | 'Field',
14 | 'ComputedField',
15 | 'Link',
16 | 'AbstractModelResource'
17 | )
18 |
--------------------------------------------------------------------------------
/fastapi_admin2/backends/sqla/markers.py:
--------------------------------------------------------------------------------
1 | from typing import Union, AsyncIterator
2 |
3 | from sqlalchemy.ext.asyncio import AsyncSession
4 | from sqlalchemy.orm import sessionmaker
5 |
6 | from fastapi_admin2.utils.depends import DependencyMarker
7 |
8 |
9 | class AsyncSessionDependencyMarker(DependencyMarker[Union[AsyncIterator[AsyncSession], AsyncSession]]):
10 | pass
11 |
12 |
13 | class SessionMakerDependencyMarker(DependencyMarker[sessionmaker]):
14 | pass
15 |
--------------------------------------------------------------------------------
/fastapi_admin2/templates/widgets/inputs/input.html:
--------------------------------------------------------------------------------
1 | Temporarily down for maintenance
10 |11 | Sorry for the inconvenience but we’re performing some maintenance at the moment. We’ll be back 12 | online shortly! 13 |
14 |Oops… You are forbidden
8 |9 | We are sorry but the page you are looking for was forbidden 10 |
11 |Oops… You are unauthorized
8 |9 | We are sorry but the page you are looking for need authorization. 10 |
11 |Oops… You just found an error page
8 |9 | We are sorry but our server encountered an internal error 10 |
11 |Oops… You just found an error page
8 |9 | We are sorry but the page you are looking for was not found 10 |
11 |