11"""Example that demonstrates use of various foreign key relationships.
22
3+ An example of each SQLAlchemy relationship is included.
4+ However, the many to many relationship requires the react-admin enterprise-edition
5+ (not currently supported by aiohttp-admin).
6+ https://docs.sqlalchemy.org/en/20/orm/basic_relationships.html
7+
38When running this file, admin will be accessible at /admin.
49"""
510
11+ import sqlalchemy as sa
612from aiohttp import web
713from sqlalchemy .ext .asyncio import async_sessionmaker , create_async_engine
14+ from sqlalchemy .orm import DeclarativeBase , Mapped , mapped_column , relationship
815
916import aiohttp_admin
10- from _models import Author , Base , Book
1117from aiohttp_admin .backends .sqlalchemy import SAResource
1218
1319
20+ class Base (DeclarativeBase ):
21+ """Base model."""
22+
23+
24+ class OneToManyParent (Base ):
25+ __tablename__ = "onetomany_parent"
26+
27+ id : Mapped [int ] = mapped_column (primary_key = True )
28+ name : Mapped [str ]
29+ value : Mapped [int ]
30+ children : Mapped [list ["OneToManyChild" ]] = relationship (back_populates = "parent" )
31+
32+
33+ class OneToManyChild (Base ):
34+ __tablename__ = "onetomany_child"
35+
36+ id : Mapped [int ] = mapped_column (primary_key = True )
37+ name : Mapped [str ]
38+ value : Mapped [int ]
39+ parent_id : Mapped [int ] = mapped_column (sa .ForeignKey (OneToManyParent .id ))
40+ parent : Mapped [OneToManyParent ] = relationship (back_populates = "children" )
41+
42+
43+ class ManyToOneParent (Base ):
44+ __tablename__ = "manytoone_parent"
45+
46+ id : Mapped [int ] = mapped_column (primary_key = True )
47+ name : Mapped [str ]
48+ value : Mapped [int ]
49+ child_id : Mapped [int | None ] = mapped_column (sa .ForeignKey ("manytoone_child.id" ))
50+ child : Mapped ["ManyToOneChild | None" ] = relationship (back_populates = "parents" )
51+
52+
53+ class ManyToOneChild (Base ):
54+ __tablename__ = "manytoone_child"
55+
56+ id : Mapped [int ] = mapped_column (primary_key = True )
57+ name : Mapped [str ]
58+ value : Mapped [int ]
59+ parents : Mapped [list [ManyToOneParent ]] = relationship (back_populates = "child" )
60+
61+
62+ class OneToOneParent (Base ):
63+ __tablename__ = "onetoone_parent"
64+
65+ id : Mapped [int ] = mapped_column (primary_key = True )
66+ name : Mapped [str ]
67+ value : Mapped [int ]
68+ child : Mapped ["OneToOneChild" ] = relationship (back_populates = "parent" )
69+
70+
71+ class OneToOneChild (Base ):
72+ __tablename__ = "onetoone_child"
73+
74+ id : Mapped [int ] = mapped_column (primary_key = True )
75+ name : Mapped [str ]
76+ value : Mapped [int ]
77+ parent_id : Mapped [int ] = mapped_column (sa .ForeignKey (OneToOneParent .id ))
78+ parent : Mapped [OneToOneParent ] = relationship (back_populates = "child" )
79+
80+
81+ association_table = sa .Table (
82+ "association_table" ,
83+ Base .metadata ,
84+ sa .Column ("left_id" , sa .ForeignKey ("manytomany_left.id" ), primary_key = True ),
85+ sa .Column ("right_id" , sa .ForeignKey ("manytomany_right.id" ), primary_key = True ),
86+ )
87+
88+
89+ class ManyToManyParent (Base ):
90+ __tablename__ = "manytomany_left"
91+
92+ id : Mapped [int ] = mapped_column (primary_key = True )
93+ name : Mapped [str ]
94+ value : Mapped [int ]
95+ children : Mapped [list ["ManyToManyChild" ]] = relationship (secondary = association_table ,
96+ back_populates = "parents" )
97+
98+
99+ class ManyToManyChild (Base ):
100+ __tablename__ = "manytomany_right"
101+
102+ id : Mapped [int ] = mapped_column (primary_key = True )
103+ name : Mapped [str ]
104+ value : Mapped [int ]
105+ parents : Mapped [list [ManyToManyParent ]] = relationship (secondary = association_table ,
106+ back_populates = "children" )
107+
108+
14109async def check_credentials (username : str , password : str ) -> bool :
15110 return username == "admin" and password == "admin"
16111
@@ -23,13 +118,34 @@ async def create_app() -> web.Application:
23118 async with engine .begin () as conn :
24119 await conn .run_sync (Base .metadata .create_all )
25120 async with session .begin () as sess :
26- sess .add (Author (name = "John Doe" ))
27- author1 = Author (name = "Jane Smith" )
28- sess .add (author1 )
121+ sess .add (OneToManyParent (name = "Foo" , value = 1 ))
122+ onetomany_1 = OneToManyParent (name = "Bar" , value = 2 )
123+ sess .add (onetomany_1 )
124+ manytoone_1 = ManyToOneChild (name = "Child Foo" , value = 4 )
125+ sess .add (manytoone_1 )
126+ onetoone_1 = OneToOneParent (name = "Foo" , value = 3 )
127+ sess .add (onetoone_1 )
128+ onetoone_2 = OneToOneParent (name = "Bar" , value = 5 )
129+ sess .add (onetoone_2 )
130+ manytomany_p1 = ManyToManyParent (name = "Foo" , value = 2 )
131+ manytomany_p2 = ManyToManyParent (name = "Bar" , value = 3 )
132+ manytomany_c1 = ManyToManyChild (name = "Foo Child" , value = 5 )
133+ manytomany_c2 = ManyToManyChild (name = "Bar Child" , value = 6 )
134+ manytomany_p1 .children .append (manytomany_c1 )
135+ manytomany_p1 .children .append (manytomany_c2 )
136+ manytomany_p2 .children .append (manytomany_c1 )
137+ manytomany_p2 .children .append (manytomany_c2 )
138+ sess .add (manytomany_p1 )
139+ sess .add (manytomany_p2 )
140+ sess .add (manytomany_c1 )
141+ sess .add (manytomany_c2 )
29142 async with session .begin () as sess :
30- sess .add (Book (author_id = author1 .id , title = "Book 1" ))
31- sess .add (Book (author_id = author1 .id , title = "Book 2" ))
32- sess .add (Book (author_id = author1 .id , title = "Another book" ))
143+ sess .add (OneToManyChild (name = "Child Foo" , value = 1 , parent_id = onetomany_1 .id ))
144+ sess .add (OneToManyChild (name = "Child Bar" , value = 5 , parent_id = onetomany_1 .id ))
145+ sess .add (ManyToOneParent (name = "Foo" , value = 5 , child_id = manytoone_1 .id ))
146+ sess .add (ManyToOneParent (name = "Bar" , value = 3 ))
147+ sess .add (OneToOneChild (name = "Child Foo" , value = 0 , parent_id = onetoone_2 .id ))
148+ sess .add (OneToOneChild (name = "Child Bar" , value = 2 , parent_id = onetoone_1 .id ))
33149
34150 app = web .Application ()
35151
@@ -40,8 +156,14 @@ async def create_app() -> web.Application:
40156 "secure" : False
41157 },
42158 "resources" : (
43- {"model" : SAResource (engine , Author ), "repr" : Author .name .name },
44- {"model" : SAResource (engine , Book )}
159+ {"model" : SAResource (engine , OneToManyParent ), "repr" : "name" },
160+ {"model" : SAResource (engine , OneToManyChild )},
161+ {"model" : SAResource (engine , ManyToOneParent ), "repr" : "name" },
162+ {"model" : SAResource (engine , ManyToOneChild )},
163+ {"model" : SAResource (engine , OneToOneParent ), "repr" : "name" },
164+ {"model" : SAResource (engine , OneToOneChild )},
165+ # {"model": SAResource(engine, ManyToManyParent)},
166+ # {"model": SAResource(engine, ManyToManyChild)}
45167 )
46168 }
47169 aiohttp_admin .setup (app , schema )
0 commit comments