1- from typing import List
2-
31from fastapi import FastAPI
4- from sqlalchemy import Boolean , Integer , String , select , ForeignKey
5- from sqlalchemy .ext .asyncio import async_sessionmaker , create_async_engine
6- from sqlalchemy .orm import DeclarativeBase , Mapped , mapped_column , relationship
2+ from models import Base , BaseEvent , Event , Tournament , User , sqlalchemy_engine , sqlalchemy_sessionmaker
3+ from sqlalchemy import select , update
74
8- from fastadmin import SqlAlchemyModelAdmin , register , fastapi_app as admin_app
5+ from fastadmin import SqlAlchemyInlineModelAdmin , SqlAlchemyModelAdmin , action , display
6+ from fastadmin import fastapi_app as admin_app
7+ from fastadmin import register
98
109
11- sqlalchemy_engine = create_async_engine ("sqlite+aiosqlite:///:memory:" , echo = True )
12- sqlalchemy_sessionmaker = async_sessionmaker (sqlalchemy_engine , expire_on_commit = False )
10+ @register (User , sqlalchemy_sessionmaker = sqlalchemy_sessionmaker )
11+ class UserModelAdmin (SqlAlchemyModelAdmin ):
12+ exclude = ("password" ,)
13+ list_display = ("id" , "username" , "is_superuser" )
14+ list_display_links = ("id" , "username" )
15+ list_filter = ("id" , "username" , "is_superuser" )
16+ search_fields = ("username" ,)
1317
18+ async def authenticate (self , username , password ):
19+ sessionmaker = self .get_sessionmaker ()
20+ async with sessionmaker () as session :
21+ query = select (self .model_cls ).filter_by (username = username , password = password , is_superuser = True )
22+ result = await session .scalars (query )
23+ obj = result .first ()
24+ if not obj :
25+ return None
26+ return obj .id
27+
28+ async def change_password (self , user_id , password ):
29+ sessionmaker = self .get_sessionmaker ()
30+ async with sessionmaker () as session :
31+ # use hash password for real usage
32+ query = update (self .model_cls ).where (User .id .in_ ([user_id ])).values (password = password )
33+ await session .execute (query )
34+ await session .commit ()
35+
36+
37+ class EventInlineModelAdmin (SqlAlchemyInlineModelAdmin ):
38+ model = Event
1439
15- class Base (DeclarativeBase ):
16- pass
1740
41+ @register (Tournament , sqlalchemy_sessionmaker = sqlalchemy_sessionmaker )
42+ class TournamentModelAdmin (SqlAlchemyModelAdmin ):
43+ list_display = ("id" , "name" )
44+ inlines = (EventInlineModelAdmin ,)
1845
19- class User (Base ):
20- __tablename__ = "user"
2146
22- id : Mapped [int ] = mapped_column (Integer , primary_key = True , nullable = False )
23- username : Mapped [str ] = mapped_column (String (length = 255 ), nullable = False )
24- password : Mapped [str ] = mapped_column (String (length = 255 ), nullable = False )
25- is_superuser : Mapped [bool ] = mapped_column (Boolean , default = False , nullable = False )
26- is_active : Mapped [bool ] = mapped_column (Boolean , default = False , nullable = False )
47+ @register (BaseEvent , sqlalchemy_sessionmaker = sqlalchemy_sessionmaker )
48+ class BaseEventModelAdmin (SqlAlchemyModelAdmin ):
49+ pass
2750
28- transactions : Mapped [List ["Transaction" ]] = relationship (back_populates = "user" )
2951
30- def __str__ (self ):
31- return self .username
52+ @register (Event , sqlalchemy_sessionmaker = sqlalchemy_sessionmaker )
53+ class EventModelAdmin (SqlAlchemyModelAdmin ):
54+ actions = ("make_is_active" , "make_is_not_active" )
55+ list_display = ("id" , "name_with_price" , "rating" , "event_type" , "is_active" , "started" )
56+ raw_id_fields = ("base" ,)
3257
58+ @action (description = "Make user active" )
59+ async def make_is_active (self , ids ):
60+ sessionmaker = self .get_sessionmaker ()
61+ async with sessionmaker () as session :
62+ query = update (Event ).where (Event .id .in_ (ids )).values (is_active = True )
63+ await session .execute (query )
64+ await session .commit ()
3365
34- class Transaction (Base ):
35- __tablename__ = "transaction"
66+ @action
67+ async def make_is_not_active (self , ids ):
68+ sessionmaker = self .get_sessionmaker ()
69+ async with sessionmaker () as session :
70+ query = update (Event ).where (Event .id .in_ (ids )).values (is_active = False )
71+ await session .execute (query )
72+ await session .commit ()
3673
37- id : Mapped [int ] = mapped_column (Integer , primary_key = True , nullable = False )
38- user_id : Mapped [int ] = mapped_column (ForeignKey ("user.id" ))
74+ @display
75+ async def started (self , obj ):
76+ return bool (obj .start_time )
3977
40- user : Mapped ["User" ] = relationship (back_populates = "transactions" )
78+ @display ()
79+ async def name_with_price (self , obj ):
80+ return f"{ obj .name } - { obj .price } "
81+
82+
83+ app = FastAPI ()
4184
4285
4386async def init_db ():
@@ -52,43 +95,11 @@ async def create_superuser():
5295 username = "admin" ,
5396 password = "admin" ,
5497 is_superuser = True ,
55- is_active = True ,
5698 )
5799 s .add (user )
58100 await s .commit ()
59101
60102
61- @register (User , sqlalchemy_sessionmaker = sqlalchemy_sessionmaker )
62- class UserAdmin (SqlAlchemyModelAdmin ):
63- exclude = ("password" ,)
64- list_display = ("id" , "username" , "is_superuser" , "is_active" )
65- list_display_links = ("id" , "username" )
66- list_filter = ("id" , "username" , "is_superuser" , "is_active" )
67- search_fields = ("username" ,)
68-
69- async def authenticate (self , username , password ):
70- sessionmaker = self .get_sessionmaker ()
71- async with sessionmaker () as session :
72- query = select (User ).filter_by (
73- username = username , password = password , is_superuser = True
74- )
75- result = await session .scalars (query )
76- user = result .first ()
77- if not user :
78- return None
79- if password != user .password :
80- return None
81- return user .id
82-
83- @register (Transaction , sqlalchemy_sessionmaker = sqlalchemy_sessionmaker )
84- class TransactionAdmin (SqlAlchemyModelAdmin ):
85- list_display = ("id" , "user" )
86- raw_id_fields = ("user" ,)
87-
88-
89- app = FastAPI ()
90-
91-
92103@app .on_event ("startup" )
93104async def startup ():
94105 await init_db ()
0 commit comments