!1ULZiYxjT3DPJhCtX1W+F_-rc2*kjy?}?-CeKVT|xT7 zfSQeWVq$_Zk&QQw1vZ@~1|`uyz?d9n3C&}OOQfy5tJ(Cm&vVzK{+J2(;(0#b`+mN^ zzj=NL1bl#eSJJmKKe_?c(*S&5UKDW~j8 zxlEap+_ER-HL+9j$qlIn6T1lZr~EZefN+8}+(@v;#BRa~r9uoquFOe0mHM6OtYaG? z=cZ?au_OjK0AipQ`e4JRe}lFDrXnbkiQD}8jaV3%W?;}f3EFJjaN2%|MR%QPBjkl4 z*hH9N+c(Md@yv!y$hNBAFan=AlC?kcT;0k>@EB}9l64Ta!03^f9(WwK9*G%xY&~u8 z$$we5z^ATu0id>#EoqmcsVJF9G;_+Xp?<>-7=tHZaP#B_XZ>ZseEWQR{OJQK#u@A$ z5j1`Hweti9&t14UF(yJNp*cZCaR+vx?6jCgm^&+Ih%j8LlGl++xk%1Q%DjxSIxplz z^2a%mR)`UUJvtK7Gf344<|f4~%%32kYGGpCv5D7T9hL||o{yE5u9fb+TVDOTy!w9r z8Nw>v`K @?ygmquT{R >`U|}dgCm1 z>Y^?o+yIf5R>hnyDp~BFCBZ3Rp1l<3a6phGWsX-=k<_B$CQD4K2$JMQLDFo7jPw}= z9*Q$afW%S3olNtRplSIqNzlr|O3liJwkfBgDe-O0>B6*Dh$KlvlKgP)t96*IU7`hv#KM%<}wr!9&4|LN15Bl9Cpr8Aa2@a~)(|Sj U{ENwQ}u zeIHa8<@$)vgw=hOzLnUYrjy{UHN-3p>7i_|sibVpYL|wCHDr_hRBQK2rEfC!kckU4 zEcTIg5Ol WckbY%Bw46<@dk2nXI* pEaJwM91HwfvT#Pg?cNUvl zt(ywf2Earf0T<(_h7Xy`1M6O+f6O>DZh-K8aNz-9Ef>p!yOFM)NSDz!VvJ83V`) $<`9c4KJ57`$W}U9Kx$xY=!-K5sn#im4c_E6$kShK#ds z7{hOx$}80n;QUL4pV;F+lXAGmg_p07E{+yG;bI_K3^WxRBY%3GPFK|lxK=em`uP`3 C nZL7HmApPJc7=&F%ZX z->>CVDyhJCz?dx_-lQmhiB9JyX5WDy{}3q(Q3!Gr7g@-~7Isxjbu~*vVjMfVYgmSi zRVU`gt+ Oc^%QY?2O<5_VQ0; U2R0vc0EhGxh{_;pib%pg6a_o99QSsUdpePol|CB!1K8F2k8*eztM#C8L= z2Tt6!2D_b_a!-xyAg@SVFW~w}AKAGEx4h?env(c9*+q6s{3gI}2K=7?#E19YOZG`@ zKiNO5WM6Fyp0k>-e_W-k=EsiF3M~=tr`|ttV(8to1zPd!a>-8|8T#OOx$04tMSg6U zat@;q#)k`KMvoo&2x4QLdO0$h#eSC@J<4d_qfzH%g+S*iI#lh31Dm(*w&uQVUYTm% zywbdU?eU{ou`RE YvI!4uP?UlKL~!m-n{+*_Qm6{9ihCyY *4CYZ=OPF7o;V|_4V z8C>wiXBD;?x=&9WeRJd_r;Lw$VwXty3?CV)6(;h`9b)AoEqJ2uO_WPf_l*&L+Q~bG z3F_8zV|ni7D|U`hw>$#Dh$MZWQuCAI`0$`EIE5R~;HiwEA+`m=PkRoX<6bpqlgUHp z=-Iq0q7GSt#`VRAKZdgSMu_xd5paE$_QBSIrP~opGm;~o@i0LI6SaXqLy|LXussc$ zRX4zb;NEwSr*ADjYy|hd3~v4~3*LcOc~zb(lnM0>LcP50WYv(@gm~C!4erZ?K(iX# z3V+x((Fl5dUA|g!8#clbzFa0}1c-}jf~V3zhlzlaz0j4f4=b9{n2LD11HJ19Jro z&GIKavEqvf=tM6@b)|@B@FcEdc(K~?VqDaSb_%m?ouj~#UYBcNoe?s{4gx}lsvwyH zL`)!HPpz(j(_({cJDm4Kq)%(^?hC}R9Wcx?(Ad`mw+A5Vd`U3>Q^@e&zkSh~n-4x; zXkTgscN)$4N5R$G*?7orw_V~Duw5<`Jy$KA4jC3~`$?OF*&OOo!gj%c e?C`HV|eAR?zap8V*`j^FpndbSqg1GkbClXU6g3RdS5JbwUbu5(wme(o=3TSmz z >vzB#=qVE z>Q3i1*Uxfs>i=aq(THv%;KPXc5N?!w_^QjtrB1 wMKNd9r59D&=b; z*O>6SuYyOUf}%!>oRp95pi2CIVY2+i-*U^O>d?2LFetnTO}|VVumLi#shT*A45Te# tg#W=9KgX)MWF`#lg^?~p)t-kK^SRk==-RW@6?h42<}>rXwW~5q{{oCM!4Uue literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/api/__pycache__/Score.cpython-312.pyc b/sqlalchemy_fastapi_demo/api/__pycache__/Score.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ebb333c4204e2065aef66773aee8546f68c9e49c GIT binary patch literal 3879 zcmc&%ZA@F&89w)3-|KH {jg^w!xhm|EqwhmVU?DDd(Zu_4T3HE zwIlg_yyyKm_kExDJ;#5s+bsy%Ul%_gJ7PuXA9SHNWd{~JP8Om2NJJtNK~cufFm%pF z*eK`cq6WVq%KQ1K;1?7+7coXnev>jcM9fi(-=fU DA zVP3Q8cVg$*EBXPdqiCFG)D>`ZU>%931@k;tL$ioh(I(m#9P@?>)qrif+$bm3VVCHH zUp+RB3Zm ijSNkFA4hC?xe zFP{4`%!L~`5fDebtZY@N7YGg}u(r4!7wLlWC0$^A^Q%8>KEAW@tM@m5zqt0NkJdk0 z1S$3gFsnyWjBbg*xkb^l^=IgkO;qsly|rI|0)p!wr`LY>MOB<54%n922qtxOVvxqe zahZ>Vqv3?iiX$Nnaj=IF55M=|w{sS{w-Ez5lF(3!&=};*-j-rhD8(!=I&P=A6gP|> zaFdLe9rCio0|KN0I+&Ybkd4$A!AQhwsP2(Qx+6%`W0FL%-U02~pTNX-UBX22g+q8U zJmI^DrSU{8?py!zz4cG-uRZwu+1FX$Xi!Q7 Bp3<(6i255+Ezfs z(U=c-e2V*f;#0DP9z!)qTEUJDeo`lNo9JI@^iLbIc}mvSg0(esK6`DkVaa+r-M?(D zPygtJa=w|?!_3bbeeX(%WFRa~``*R3g3&;Xh?q>nhbUCpQYG&1WIxz@c_-JpSh6Q* zsFWr$BD=uNYr&aeDgiJIZQX<5C282fR~z>}efH>swFjBCk8^VXMetf8DFs3?5zB&z z6TxuA%c(&!Q}2vS!KV=cgy#&T4F+ DQVO5cZ0cd6A~ zva}T}ZJDdt#+;>SIhnq+Vs)-MT60{!_tKK1KW_pbJJXk6>`=us-fo5*gGs0scNK&} z*?l?ZF)1`g_3df8!=~933+^=P+k4$vgMX9GQyo(WXa}46T~lR7wIL+CZ5nDrSYwj{ zb5El-E2lT43|hYNL!=!z)iUz%vpo?f9dwUoqPnqucXs2Cb8BCHsRF`lR3q;SPe^gd zqJWCwKyu=y8heTZLa#9e1+pa`le7f#@=BCcV0iGYu#^Z-+z5<9GKX(W1jg}{?5I!` zc*y1nJgH?LjVI0a4i!W8kWw4<)a-%Xqwtd^q0@2Ha eLsv*75=9?f1aI=a(?%T`a`;CUg@PoFu@o;NU|S{zZbQY&X)7Kt3Kl@$y? z Xj(`KyR+fjy@;=rKs6!g)ww4jHh(+6_Ca>z zUd}5hIiaGS`mS09Wpg~K!{1mXR}+Dp0DhSX%FKvFON#>W3dobnov(wu7xw8hMp}SQ z1-TP>+A82ZzSvT9_W@+B&ATD{)M&etnn`8&Qd3u qyJ~S&YHY(7ZNF*D;Zo1p zLeJTv<;}ayiq$sTdB5uyU77EF+V{)8e0^8$2M_z^`X2G6GXsS)1Nqkn|5iV^>T1tj z$e+2o 6xg-KeL<5v-@150Nu(W5{Y=7>JqUBWWouyR{ z_0A%%f$WgCRp#SUVk|`Hvr0B _-E2!$?vJWy{d4xB?fKtig6O?}arn2g}Fq#tNdC6SbdzRWQU^8~eQ zpuQsNdxDNWL8qRelYd8p-&ou~?@pV`0%EOq4&Od}S1K~@Z=4OY!OXdQ_nS-3AFk9l z&Pth^+2Q=DD@*n7thkyp$3OIK8wJL-Y_XR)7@t}lWgbS*Vs<{KJ3Aa=J!O{CT$<*5 z-D^drYukhl9m$M-7~3|QnEGX>yUfA()N`oJ!w3rOp67IjD)5$BN^7JFj@&*n%M}^V zwxG-NcBWz3(Ol+Wd}?z)r)w(JP-bCP?$~YCqKlcGj9oDcqhc0DFk9DBHqx1i9)R*_ g2cWbrP*q~;3rv09^?H%%{$IY~#5Vl~atR{wZ@}A)xBvhE literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/api/__pycache__/__init__.cpython-310.pyc b/sqlalchemy_fastapi_demo/api/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f8898a44f831b6186ab385aa7beb2ca3d9ef4120 GIT binary patch literal 180 zcmd1j<>g`kf=^7#vOx4>5P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;x_`vsFxJacWU< zOn7EqN`859Oh9FFMq*KJKv8~HYH|sPUy_lZ2jyDC6c^?s<|JpN=2ph1B^H+?7G%b! oq~_+w02wjy@tJv |CIqmRMYpSdgh(P?VpQnp~n^T$q!Xlbn&7 zTNw|Picd++&DRI2(T|VM%*!l^kJl@xyv1RYo1apelWJGQ3bcq3h>JmtkIamWj77{q F767#^HjDrO literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/api/__pycache__/advisors.cpython-310.pyc b/sqlalchemy_fastapi_demo/api/__pycache__/advisors.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec1265a8d8359f6886fa2b39c520558b86f5ddf7 GIT binary patch literal 2339 zcmaJ?TW=dh6yBL#du?a!I`^a(NXr9QLdgpfQiTwuY1K%`jYy(OD@)eaGi@BaUNgH} zXmKT=6)HuMDp5gO0&P)?8c?~Z5|KdgKjwiK>Rg_9fft@QXLdJnNW)q?J~MO9T)y+2 zZ@qjzr@`}kWqILqu>QbK_mhFnEAaX+5KUtmBMr?ZHgTy oZzF8D%;%7U}z>lqxUlq5u)X z!X^*R#&uxL--Bq~{dMEhZ`a>_ud{OH@ycT7;f>DHgJmjv{J;r9zgmNH$~5DFQ*V@X zfuytxK6gZIz8arb;L%FP*6M0AJ1Y{0Wli8#|C~B{xH1RG_?1)jCiC9%E7Rv|^Nw(* zg}1 oJMV)yXUKC95_&`US-_%DqvLN&HeG#d1)cM$!=NL%E$63 z(hM<(MZ_?4AP0@QAJiz=$%8hYT|tTfDM(2hs%en|Luk1~Bj6A-u+{DJxK6T}52H94 zx#2C m0y7{B(d`nTy4VrZWfZ((rqmKInc_ltBEnFii9m`2(4gTXfkz;%7RitzHHex4 zB*PX1BzH&eIK*|Mw*$MuK;MDgK^S`yc2EXe)r7Z@+49NR>hY6v v?VjJc9L1?-umj)UhfH4!k8QnB2 z!C02%wrI$D+LT#KNXGnTl_`088un8tie9vkcD8lm$V_!+c5d=md3Hu1|3ZXryLNrF z{@ab!r4Ks~zgoL~dkfkSSM6N6vvKp@>XmDqtG7{}T@Z8UEVr`}6rjG4)F=b-$dj}U zvkoEu3;rSSDZ%R_5&B~A6 l=AjmldKo?&(OI&7Nf-hp&;4g#1X#N;91DXYOUW8v- Wx5)FPm^wtP^nPOH_LGb`M*am5!Bz(V literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/api/__pycache__/advisors.cpython-312.pyc b/sqlalchemy_fastapi_demo/api/__pycache__/advisors.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5253574748f6d326e9f0ace00c2380a2ce46eece GIT binary patch literal 3037 zcmbVOYitx%6u$G=*X-`J^g(MM3KXcTp`)})B#1#lC?u6ogs?H$EPF3@>%P3R3k6Hk z`m6!tAJT#nvl<~KEx0@)RZ&U&gW=CMG@(o+{II*0Ulbeud+t28yI4e+WbU4sd+vA6 z{mysK>{YK u8rI8;LShC@UXLo|gC*c3{F7*J$N z)I>a{l0Y<$Nu)#b1Pz2hEEpx4EzuQ^5sk;YLqgFmZD6zK+3he4p`@uBgt|>l75SoG zz8Cd!quhvza8T$K`uSd=6D1jreqkO9qoSqA_c@=f z*GB K;h3_XsP81>2_=8-gZx)Rxzi`7en=~O zf)G6sUXh^jZW2l=>bsF(B-BNs`vc}w0F!830UyOoLTyRx*F3BeR#aLC!CY{w&%w}# zrsRt2^5SuMae7 16?|lvQB3P$Qj1l@%J8qpSmHo?>VEB)no}Rcl~? z{khAoyBo*djp>R^!{rSV?#)?oGp&cY0}dqw%p{2>S&9tDLdEi81=2;h4UC6wit9xn zL38~ {pi{YoXy|puSWsSkvE~$bWh$fBeVX=NEGq&rN?bl0QG3`}i=e zf=M8QwS7%ClD9}Q x2nV5K&|kpJ>RelU~! z_U!b96L&6sVVv&5xxRDhaDHI$KE`t&eLwZnpy~PZuYVmGE@j`?y~VI~*!8e_0xT8H zm9iWPhh3K}UB+@`Lj&A}lUP)PE1M_eo%2>}W53EABHST%|xuCHGZfehu${NROdm z5rc}uT#1eaERNbNr9&&VcUU@RTh}BbCmaZ4%1S^h*-)Zg!^0xS(ryuPg??44UG|Zt zY*+%f%07$#q22O^qr0+Y%~@x2X%o|_^VMq(vujd;p|ZoSCjyPU&{$jIG)nC-qb-_y zS<-D=;1C3N2cdbxUm2t|KgdmGjheJreVMX9Xq5F~t?5Baa4>H9>qp*bjdp5$w*~kl zYl51jdPmnp)&%wDr-_L;nCygWLLvoD;aE}^8~b80wdf3 (Q*3y?? z8T28freK^AIF7r8TE|iAO|;}DYQ2TpZ=p4J?MSLTRNrTx %yT-Ll zHa|Po_WP=A=dP=-+(ja{i8~rfFFn>ZquZIL3_km`VP9VLxBhNcK)f=;GuIgj@lF%2 zZCDy_YGs&hrI;MIrGUw73zOLlll?Nx7iM^7&UhGReSiJHu5@=_{Wb3S8?CFyUOca7 z2S{O-%@%H0&&F7}l4S!ct!%QMC7EYfCNJN3wf)NS-xRj79&>3AmuY1XJ=|C`+fa`l pd@Y0MF(DfJ8?$B0u5rt6tZ2*Z7ztRs7(AqR&hgNESLZ=5%Rjj_@)rOA literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/api/__pycache__/c_lass.cpython-310.pyc b/sqlalchemy_fastapi_demo/api/__pycache__/c_lass.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e6f1bd03728452e2a7ae92140fd7cb7f01e41292 GIT binary patch literal 2254 zcmZ`*TW=dh6yBL#uN`~sBu?5UZQ6uFFBVcFAt5A$P*I9RUqa|bNUKO@v%r2=PW*RfsbN_+Oq%$alf z&c!ZgvuO<;Qop_MZoj7eAs5|G3Ksj| t51N*(t>vUZ0<~(|*Rz_?B(?Sv%|J?3_AFc>Vr>J>U=8gMQx5BaNb}W)IP!g<)dS zJV}yNO{bWqs^};peRP1Nsd>~O8DgDIRFS<2BsY^RNalJZ`{|Zga)1mf$q^-)r=v7K zs*xcjZGhJr877;+hCw!yEo6j@lC3o(wy2YBpl2-BWs>b=htjnbbZsN!V0Gd@R$ril z%Cbpzk{6Zq7)Wm?S@IIuRl^&xbUfTm_9(d>WbYxZP-sc)3x?=>Yxcmwau`r1lKW|e zE)p)X?;Jin`}QX#S_$0pqDZ_KQnpk;B6)~%4m-e_$7oO_^M!=SmKb#cS}YYkhjWpZ z2Qi 8hlLuA#-LCP!TMNUr`Qw|}a1rap9 zTB~3G?(w<1kAJyUz#_+Dk)mG)?IOuT-*?!ONSCDQBA9msCi5jM!;c@y8}LrU%Xb0^ zv}LrcEubo9R)7g2nCLb9ISO>SU&Vl*G2@ dT-dw#IIdEWqef@{}-EZobZ~yt* zmydp~HLDL=XKM8uwZ{6d^|M#+V3Fa06NJ220{4VTXyCYB!C-x$Mx-JiUBaX{Og2OT zv%KVofZWm82z;I#nSOol2&atCz3(oP^2dB`cBypSVg4*DFVIpT*TM1fV!V89j(_Ai zUg DGQ#I^!^A~W@A+rN|HFzht0 z-fz_IxukLBW^?s=gaF$D2R-2Gu(1K|4p>CsR`E%^jCnRd9e9@`U|Sae*uSI?8^8jT z5v)ua22dnk3Z;UsOe%ov6qzq79~Dp$83jqvuZmJt!2D9tCDIQr@lERnvXFt;c33 zQ=vq-zVb!u+E3kK)mOf5Ub`JCpVohDK0NdI(&^^CwfcjLjf-ngcK8?-8A5r9xvFJa za@4gT46XG$kZ==_#_Bn#_3~%+8@D=lbv6!X0(+EANXFnFx)qV|T;B~!61(=(gQKi` zz!5J)p;mP$M>JDFOd16|cEN}3mPA&~vrwp>j1uX&JdpLvWdm4Awg)~ZtgbXqsfZsv zyw|vJKg#c;hu0dXRz)UmWZ6#7_cCrJ@Un_|raRLC J+2LZMv)MBpCS`8t9hfso z5VLnaU#vVC4G}f4qV&j0ROwNn*}I;1naim}+xN5bR!$Q5f1nAIML$bMrOX30gM&INNp{ICQ>~K_e|*+?$jPhte6PgTBSUTeN0(5+FY0Bx5AHh@PbC$qJN76E zWl+|1_udy?IQY!3B1$3|jSuR!=TZtC@^iZ5c}3G;1Vnqkk_^ecew*%&P$isHLXl7` ztZ8~VPMER>OjSmVzF 5c>-3?VTCO`Bk&pX0^>XoktZ?ZoLFZyO)DRp+0n^Upap-}d+>gxt2!oTn$} z?71z~XS|u i_lB7F z8t&2B+Dd)U>lLgtSRVEcg& XQ`n#obe=Nl#KYDiY+(e4GeEr(u%~N;YJGprIYX0+g3h!Kn z>frkoU6K_oLZhs*m(cwsO!uWPph?w2Q@HXLT77>wf8pa*U4f#DIv-Q$V_plda@W60Ok((IV!;_fNnE%bPF~tUDu$-NW{p6SX4_= zyeAUyYM9=TTQ1^i1lZ*4Gqcj>oVb}`#4uR6dAV@rhLI`@H_sJDuIQ4 CDJO}MNp0n36u4s*xh)%u}fyy2=F@6BwQ zlO8pz;kh}_p`7#3w+` A*%_S@c;iLTs}J#*f0&J{M;raOClR_e@&okqT(*ZI-x(jP7ur-R(YGW!3? 1lX1ELETt#;)CSQu{haan+9hIw!T~#CC?k0e_3`FbSSwo>2^y5m`G(x@Yww=!jF5 z;ti*_t`4rb9XhbYdc$zp;BTtl_TXjl4&xGG*OtMkNDC~H*xB{R9;B?{t)y7`9@MJ9 zrV_WbQ{%TrOvHgUkdJf$7+4pggGolcy0}6px{ydES^DACihm^(QT&83WDJm )q z6;qz3KY}S_P3<_eMS wAxD?(q`dkK->|({ zPI%`j--vJYNOu49)5E@5?kDp*c1`zPi!T$A^JktaVmI;QyV%_m2>(;A$b(q)qGIDn z IbC uqHdnQO-rJCAe><@3uyI?yDt8wJ=)aXbMH}=* zJ1MKYi!;_XI9RjB!Ncg_k@>yP<_;eDvSOK(aoaMTMeHVCV%>EAUHn1|FM^{W7MsvQ p^GNgPiR|ET^DMW0zGM5 vL1b6~DXpp|||NPcXrN11JzXZ&I3ONPte$W(*0W%-nHDBWu@KMpshyUJb~R zGqh$VG!q3r5SkJiAVZpxPJp)4kcJSxcBcQq{aQ=dpZd88g`Tr3S@MHUujd}^ +e=+U%)VyE?qLT5L;u1z(KX^dnwhuFlSHg$AccMRJgI8L*s zW7(E$>)C)4w1ZB_4#~ce4LcD#BHLy*>cs4r6Sw2CZ)Mw@cDvo_usdWwknMEV*lV0F zyUXdeyPY1p$LY0uoj$wI>9_ld#>uQ^ujOl}*0CTD^1gnJg;= a4W`aE?H8+ChCbk{c+_6Nn2fk>CcS&uFJ sPHn_v+Oykw?*phgmste;kt;e#hzzBkh)u0 z Ip2J($VDkZ{J=r( zx-gQUzVT|t_59#|sgcUUq;-UQNj4619s8U@HeYgh&U-oK^1UzZ_dAv zH%C#?Z)^6YRwCecFB^KJz)~LfyPCsjx%%iH!BKbl67}Jh&E)s_1I;z%?sD{X?iTVn zINQ4BEbh2uaymYe$FCZ3c}k=wM~WK(+v=6`wclNyyY*%5;-~Z1KdIjM)7)3*tCiF9 z*RIXoxm^3@bp$}vmrpu*# 85a z%RTRYa}K8e_04+=7fw{qyjT0pm$lPp=Dz(%8LQc1H)zk_{LB2EckZ4)Ie+a&_4WsF zw%P|b;0*K#7rijQfW)*wQ2ZT)vbl4%`q9TVSoz9lbu+NhMIR{mG^-4K%k_%M4D*BX zK-e 5O_t*_tIxuh3r+2IFsA$H*~= jvXkaCsV>XAo5c@ z?P1@W%;)Oeon!8s*;F$(>SiA_d1TWRi?K`7vmW@x}Z~LU*`O@}ny9lF|cl*wF0+ zK|=-!li&lxjNfl3!4vd>cpQeOV VK3_V*T3)iKk$4I;^~tVr-;{+O?avs_$N^^GB;k z^!)f#8m O(D1ZN1Q6Ax=w&)X%T%;M1~okZ88=1YZFnF6?I1IlS+Qnx zunmE&4wlLnR^1mbz{2y_KdlqY`I9S8R=xS>>K7kYFZ=;$2|QIjeSP7bO7%*mcJ4;? zlaHm31QJccl9>8kEdiZ}5|s2Z;H%(Neq6Q$Vh$`*cU#7VOvrMNvqV^W$Btp?880Oj z4=F!M-yw^NXHYzg0@o4Gf$*)gtPSAEr*RC!#Wyn^cU(V^ $z(|#Hm4|go14RfiJ&{1`Q$*sOd<(G_3B zC9p$?gk1T@FyXd?Xn+6!+>2TOz>6?A-KN6%E#;gU71MKfuGP-|ZDr)7buei>2*6^Y z7=uok0KGu?R>+J#9rDN}2x%x9`el8_IIQKmpjhao%}^{%Su6~uduAE#lRzk{SeS2{ zSS-qhyTgMpXO^0gR1+9I1VuK+kEgRm#*;-T`ko{o8LtaxAz Ty zpOLVDU9h4jSwn3|&0!_sIh|)`96;a4Ph8D} W9$L9 z7%lK`Xn~*9;ioI$-v;pOz%+8EmFX2Z?1o*6Si)-;TEK3(L8;3KfG4B&WzbYXygIn@ zGO(EF4+k|`hhBn&0jH{{-h-G@sGs)@U1GWq&xhPxJ#}f}w^vpP04RYly(FhGv=P^q zoL20txY>=jR!3xEW?i5MwX1 0IZgYZGNDB*AiG(1$s=SDjwI5H}7P_dEp354Bzrfg-q^< zz+0_AO#H#7+LEi=FlIF7tH3*xz2)I*`Qc_kRQC`3Vtd=eEF{&m+Q_ D;xBB5^aj`Y(GTs`;#d`L0NU&OnCI{~5(D6E}CX* 1^gq;~_ox~DzOx-^PtM o95%G!01qqW4Y1aXjO z6dpsMgg8?mE=`HUKvA$E2Bs4OrOC8^nBk9%J!5%?4s>cc_OHrGI{fW9cURKdaRSpF z>)x~H-h1x7=X~d}{>ElAQ}AqHKj_}+p{Rf3OYw0k#EowmiaJZN6iY`bo(|BwCZOS& z0K;noS{nJ9sE*eM^n_-j2HqGj@}_`^ylbOo-V(47S{JqQwt$Vd2khisA9e7~fRnEX zRFHQ=w34q1RPnBWi+2ayyeHt{mj#yb)q!fhCQw6D8j7Qblw$>Ix!Ueu77ttQStDoU zs%wBTY#P$Yd|0Q2b5g8%*fIpS!H4jytc|s^j$!AJw#3zNmLXbx>tfgnuAZ%gUlphC z(zC7?b*23qZnM7|_ODrDe-FECxO%~fJZ#M^oZ4GBb&ELv&pixmJ!j(T@l zmtxDc%khg!S^A%AB zNL;8hJR9Oo%QmazthtSxd+sO)&n07bol2Ik*W+uM!$bMBlIg)m+YZE%2~Lm k^kd6Gw0Iz_dZaT!&*jI1`{MrloP6v(27SRaY+}A@R5Y1VLQW0u!Av* z(!mekZ)}F dtE2H(&;J+~)5DEBi$* zB!r*xw Ct@uscRpM{O7N)&15cI`|Q=3^Y71I zdY7yNyG?)f`s`aD&i>`aB4ci7KxRmKF_8>LSjifW@$pbkZ?GrCbCQ{l^aRCFG$ix_ z9Xh7aVFR8{c}&m~lXe4fmP%<(xKhlCN-!RCbSD_eRyHzAvzlS1n17z96D4SLqhS_3 zDLtAW<)pMJ-LQ5@*|pD*G5`#8?Q{JApCl?(eYfe+Q?oC81rVM7;&tGcu6R)+S-_Zy zq!K{8S9k6MULP zCgYuD$lG{9f@p*WQHYPQ0%clc69>`U!g}B!Ld3_QNmB(6Wvt8^8V1*9y<0{DU$6ak zTgP|yx(t)u7?`j>ku^Rs?QEKKZW(iK$ysbUhdbwP%2hSspRFQiue#|lR_N1hg-QyM z GO)0gI6 zK9zs()XZBW`FGzD?g0S;YTu_P0Fqp)KoWyg7)(UK6^-4oPC^log1;(W84)1@MY#mW z`phyuZ5VYrdxNq^%b+Cawc$=1u-S+W0sAJPBz>6VD4$OF1rCs)sf#2yUX%$6q;~YiOKo*fiF#DOce-TYsiL=dPY~uNrf&DvnpVZrThEeR}szCuOOh zG<(O)-obkZpB*>*)2%s+J^iqZYm1Tt5!eebjg}^uehmmUrU4yl?87KNz+EaNQQZn+ z SHZXuwRJVVZBOuKA;t!#dyoG>63n`H{kFJQg|fFQbMi*85i z0c_9@ge}lO<}2AxxDUBop(*7&IntQWW<;>?D;V8_GqynkMzc2*wXGPT%5!%6ne92y zy-7!OZ>1~^ljap;<`siGGKO*U`USdo$T8(P8F+pEr87Sw1kwcEUCRByP#&U5g%3V? z=k$Qp0aL0Cz$-;{lwpW}E0%qpR(!St$|4(gEF4X;Trde0RbuXqauWG)=9RzYPmYw_ z`Bq;h-U{`qnN(CkHp$0jr_(1%Nl4NJ_z}q_C1Xeyc{GTHh-{Qao>ZJb;{R^Y#zFXr zXk&=~dI}8Da;7Dd=x-UX+?d|`ow=^$0ncQf8#ixFw@z8?3zLG%DJm4Fc&-SoJ^@89 zuusW9QZS GndR4 z%_Dn8!&iDf?-@7mQ)|6r!hR@gJXF^Dg6M;~BGKp9K>Vb3A)}UJ1Y}Rp7~Y0Fi#5h- zSsklCr#VPnG^q3@>j$$9$viVB--0Z3?aR~olY?`Acu&qbSTxENC1K8-?9ab?9zF%M zqAH@d(uRq~d{62{VigZbnuzNfMgaQ4z0Iu4Ckxa#DB{Mp*cXSkORxG1X3*n#N2` zgWkceanri=jwy>x!E8}`u4RMvF^fN|^~>SBwuszfOesTn0eVqCM8A&%@ss)`-xa0E zA!G7qXjs?_!a*k_;I;!TD@2alGSW~h0)A;Pin>-sFEYpuz=WeX>0W41F?EwB@0bY_ z+B2DB |Q4c2Tz6*ewx@FPpo3-Uh{7^sINCeo82-(M0VCIm^>6^(@wq|%nO@ffhMf*~1E zV&ch!fH7FWU?31fBa{U++eL~1Q_iKv`{6RlD7RhcgdxmZ;@=_T6d0POf7Da-wsGqI ze^TD>sir)&;d|=v_f*G^8j3#5{0OrTGxMaKGFASrF0C)PD2?&u+7q=W+cPV({=H*s zA4%7a)BFDAboYk_9?UlHm~ggERe1V^fzV)UcGDvh75k XX!B_Sb7@&WstR2{JW?exCG@PoUX25;MQ83_}vG``f zH!}riw;*Mutd4>WDLdW*B^Gai%=LJSx)XILpUnDprt8M(T~nL4jdpz&o2TrwBU`z; zfPH57b?k8ALvVc{3ysBvzsatB2p8_2+Va3v{g;k;$_NXq))cVM9J!7iF5CkPfh-v( zYi-D`+k=K_n|f&9*IoaBE%mfxfGJ>?^=>BpDC`WcDBxkDct=U`S?lubdRggH4?mVY z@c1|Wc}fQoHWaYSuDXx(R}I(kwRmYDK@)K4h7%20N8>o%G}V0X$mXF3<|!?`9(RXs taM^Y2aE-U10SeSuT+%#F-!rv!$JNbWDod)!l8n4^q`Y$7Jgy`d{~rK3<#hl6 literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/api/__pycache__/statistics.cpython-310.pyc b/sqlalchemy_fastapi_demo/api/__pycache__/statistics.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab56b072df6fda43c18f2acfb21543ba92106d0e GIT binary patch literal 3932 zcma)9-BTRL5#O2pxVz=<009z67$HE2mCzyiOR jQIN=EMPz2krgB}YwfPtSBuPxo)8hon?;4fyGQ z??0UwG>m^?=lHJ(oll`D!3{$gf<;Emd=_(`$EI&Gl<~-lZQmx|jGQ><=ZLqWd|dDg zvFp3>fIkoy{bF45OL5sR)3_ZC#zX!PGeWj!_`_hyiO$6%{s@icqS1KFA0s{=osTd0 z7vgb$oce`mBEINfB;Ey&F8P;w9>tUXB*~9^b+i(!F%Z2IPx({vW&d(K?N7&7{44Q{ zKNHXTv+ 0!=vT#zAL|F{J;J^*-VZTp#2>hlkhQn*(T(}@cpp8Ns z3++u;oEH~m#orujE$ z{*~_h88J(~&B4x&YntLJXwG-F9dS)8koF>Jd!&6`+z^YPo%zMZP1pzeZi$LmqS-fT z_AQ!yTV!kXX1{yn*?Z!Bnq8sUAHeLBJN;1Hq46ae|J8que fBI*E3iV*W59* ng3+lpav%d^OlewqaLUXEUfr+6}h1s?=B7O_OF-1yLY(bO8)j!)>sx z3z;>T*e)&g)>(peD(&%=#p&h6=}#7?SD-CJ+X&NVVThp}5TUBcIz@U_^Q5T@pi|ur zqE@JL$j0?XmkFM0E;ed5rmp+T!58nA`_R;HfVADz=vW=2!#ccU?%BKcW1}%@87bSD zV#cn+jCMZdf~981*<*sg;D2KR yLJ7PXZY~lF8GsmSR7Bk~F&AJL~HED2QrL!g!~;30Mi5^{NQtWF46GJ{T&^ z9qlehfQ(uaH&-TcUqe6~gIm@si)DZAtM(ik=p`J1RauUbS`eufV0!AFCC5NnyWe4A zA4-|X44bA(rI(XaFeoo0nMQI2$qW!}N!XEQA?-CIizpvDz3M1P)j1&C8f9fR#PWaT zuN}@U=aqaH#O;wKiesn%ojt^#NFk;Z(}-C533CZZA{^|qRgcN@AlYZ+)oEu&(V5ey zX%@{8EV%p-csv$(ywnn%uLA)xOeUN}9)-QLS8p_1X${qSKRn0S$gOc;z%2%j@m+wi z-~d 6mOyJ%_s>{`8CSV3O6E0;e!<} zLT(*eaM!qpS?G^!t207B0cwEd-=cktx@N(tjB1K`-_Tu{rSd>r(_x%DhZ0Y7dvGZ{ zdQdDuJwCvis9EDgbn)CGd ~Z-md@>lEI#=XPzurH9c?!+C zTz&_i_V95(=pAt420DJD%J*=Q?z)$d{{YFU1xp0E-lKxxN%($@tBoCB?dZAj|E-Ai z>y0a(!xb}Qq9vg)Bn`p^E&B)1@^0%~w@ymjd;ekOm;0r(lE_$M7JRoalnx5KzTiZ` zttc$QVWnS=Bwp7N(=7`~FlllC2?9<}pJhk{X|Ms0Ls`OU4uBa>oIiio^cWs75iCm& zSS8D# ;qHcb3qQH&fME|YE^uRO03>;1PK=Nv;7xAay)4G zu%PNpwL;?kCh?>Zx+Oskv#(8fXUiqx>W!2h1yq=+KG1zehl`Lc5pWXIe+;37RjN1n zWr$%b3Re)}>N${6qsWSE8kz&G2=9*~8%K^Wu)OV(EPu!ue@%_^L(Yqb`SLi77P-T$ kYz$>Nm!lQy=cAcs@#lQr1z8@ni?8#Ad6u_8)0$+z0Om8of&c&j literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/api/__pycache__/students.cpython-310.pyc b/sqlalchemy_fastapi_demo/api/__pycache__/students.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..de1ed86734b09346e1ebed65ac9069d9ac80d1cc GIT binary patch literal 3050 zcmZ`*U2Gdg5Wd?xpMP?3oHR*O=nu3&Ykm^ofl3G=s)7U(DusfOPLWQIcbi_gv)$b@ zG{u!til87uD-nJK2nbMG9{M8zDnf-m@PZH$5|8@|w&SP12O5~!yK|h v$L}^ z-_AGdYJY!DgXjA{PS5 HBqRvjN)Ato 4_SvCs$Z-eg`d~b`#y*t_Tc6x`}X@lBn`!%s`jXg5y4q8-tH-X;G^m=-C zvO?_rUG#3HyAgCZ(e3meI^KiVs?7;{uhQF0H|^7k_jT};i>A!(+WW*a)q2RdOh3wM ztU`tCfBe~J_da&0%xa-mt;p2Vb;f6lx=in5LV%=5r1_*LLYa9=X_S1Jw5D0;(kbZW z_JwuID&eEMo+=u$KOXJotQ4~D@VOer;Xpk53=_3#MX eLKafgv)*$(L0eZfw73aI~OQWjYpq zt?>~ME 5dG_-~efE!1QhLHfi8Rq#G zXcDvwm{dvRE`(Dwc~>a{J(El;%%cYPk$t!pmLNLlqp+YMa|H|VxfQyH(-VS~c=^Dd zx(&lP(=NT&JaMt8tElR?b>+>|?=(-&U%7O=wQ#=m*3s6P#r8LEwmv mM%2BZaExgM41om(jdOlHb{NeGaY(U0UwLni~Tf@dRiVt7&rPlGg!h6x~9 zN34bwfn=$u`BqTn+ps|&S20O|8##!ab%VMedTzN|p&nAXn7-k{$m}p0!`$t`aXsRA zjUmJocNe&T%$ZrDul}rMGtF;@2_W;!5e`SLOF$Jg`X2|~LqSmp2_@8^<~(@?fPmmr z2_;nwodw9$I%a));Y{oJ#lOCvZ=U_2`SF>riR=UFgmnRNQzk9S!jk6$QIWrLuqUJ3 zsaZG=jwuS$3R0vzza9!B|67L`JOJtf?UFg 83_##IhOPqFX8?k_&bNV<30g1)J+onoZJ?K;R#z{j^mc-trSwvumujTM zPNkQQ^niM4+zY6e0qR9rm95_cj 0YnAqc;#KXbDxODzhXYr@b`{%mnlZYd_bj5H03VS>SX+X^_ zX4HZ4J3*k1NajlPMNd>YoS8G~RYVO+sJkk2>y?9w4bE^fnNSX=oP2Z~NjXWla5vh= zt!0KCf=kV-Ogs6+s*(uDjtoVk>!!!hTH}}-yTGPEN|QM|gSn9-dB_j=>e07AAY1MQ zh0br#K+V|!pEX1wAi(TYL_s*?YyqMy68sMZw9t_j(bWVO9}8JGK+==a*Km4httz_f zfcdyY+9{Lp`(a$%BGd6j#L*XSV1piUOk$Z|y|BisJm6T_q!rHA07Q v>`umSL_ysr;7^d!>-IAtfx`yc$W!3Nh@fg=~)GAW5*G!rZb2+7=-z hmO-u(ll((c neyQ>KX zxfLW$$d5G4gao(EBu?8DWo%MUI#cMho%CmB+8 m!C}(IwT3Zb=Y% zi5ucX;U(*YF*(!#`nH=j>9XjN?2>mQR90xUz}_g)JL#KX^>JXyBKpO8u|eE0**IaT zwVLg-ViVZk2(NCx*<` t6wt;AAE)p{Z$k&ytc z+6E+9hL!-MT7DRl71e%B8xe^^CwE#>!r~xEbpuL9l#)tc@38=@x{cb?M2aX P44S0T>(sJP58?<)fM}s$Bsq@k2AI$3oL%m(GEEW69I1t?CV&*n!WN zA&`QnWQoYZSX6o;mJIeu@);$S4$gn{;`}?;VC{GRG9Da?z(Uip?P-!4mZC~fJ{yn3 zqd%1rBVnT}EJ}$~5XRJ8-jg0teJd9ihJLacObYPI`=Q8DU$`hw^Q_Qa6uR>Vr?_ch zPwvQVyXOwyl4lFMPR#Hp3-*(D_@-IDv&eVmpO_k+;d^t3OHN RJ$-<*GQ3JAuWmQ<%G$x#y12)-!7q($V%;wMmKnxI(t_-gq# z@4&?Qw{zv+UtgZilC99KGI5D)L%|}SiKSI*JeG(lEBJ?yz6kFF+|{!b{ZJeP?$FhE zi#!~lZm=)V0p=)hAOLzu7Zf0C1n`&$ActYgz>L};!_`#>%Xl2n!K4EO)rnJKhK7F+ zw6wu1qazlm|J7X3RTR1a-@boXXN3OTk&@G&JNA{P=~7D@4Tt#xs0ZGSM$JbGEomD^ zDm~Q3=`01?Hgt?KSw=P=KSpGi57Z?(%NU?o5fmh}&hJK$zC;?qL7KmO^X{$J$~VT! zZ|4cRGr($)kyadzo`DAKRA}=zL4%C3qJ~d{3EHrBwlt)6z!=QP^5anGNYzoo##z3r z$am!jZ*7?259AKtcKQsm9-86%3-*4Eng(!zZu-3ULLw7aVsOZlVhn@u=uy> eI_NeX^tF^NJHiGU!4dfAWNk!etkS2sV>gUMUGhOFba(hP zck~qbo|0QAc^gaq7W^0dB~QZ_Zcb>*9bV!omw$Z+Z4W|@LuX{P9JcnEZiQ&^P)=Bt zS5`p3Dz9YeVY9
{(WSI`opl83BXk@-${Q2%*-_qOkEC@%lcB)kt zavo$bjCae2S7VXN>kg{rIZh`R>`2dZq#YzUO{wHiJQh`mcFGZ9jamk`d@Ge`wAu$_ zj=(Fw424cBevOpmTt%V^N7;R|wx*)3sbJf7$KN*V4;KBwDQ4;iv%3xzcO9Dc_g}W( zcKXNc?+U*X^1J`twBwF%Q~v3~-q4Ki`GV{DyS1ct^49K8x@P!OMq2wy#&ushSa;Ax zFa8U}08Q|+x^~?CG4wnXIU(-WXtFx$t|I4%o`@`~-D(6@m4|DYq)1g~d@aVpRU;FP z!Uc0>ob|1ororC}%l`?yGUg?7kk!&XlkcDAcdij+=bVBOVmkwLV3TSy?jZyNJHe!+ zEs7wLD!+VR=}D0U!I-0R%19b+MFg2n9N5yaJZ#0arU!1fk--SulJFO#`sn(@Qa#lS z92O%fJ#TleH(bUGlvJBRT(}T77Wi{i<%oWhx1>{WJ7;4_MY}qwEW}5GU=hquDl035 zU}#j?bVeb_X1qzFdkA9t0Y$dJM~|)ceQ=}B#HIb@IJChLrDP98nF>qO^ndLX{rzcb z->1};&!~ m@c+nP~F^Tp=N{o}jxLUHTf zT=O*j XU7K$yN}O!Pu%ux)J<@7eW}h}Vc|RH iO@9~zr_0 @v!b!6BR4SurQ%ftJ$z-r(nSj zl uB!RPy+BQ}vsxX597nu?Lmx t)pb0II@&I_UA{0b=h~*}ZrHz}!)m8JnhyBRx%~IBjx!%yVnEUu^M7U&Dfa*X literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/api/__pycache__/teachers.cpython-310.pyc b/sqlalchemy_fastapi_demo/api/__pycache__/teachers.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b05e847670043662e22637484d012391d82aebd9 GIT binary patch literal 3085 zcmaJ@>u(fQ6rZ{C*mifiEl?hXDhsHvVu~6P<0D35HKL}XU^J5^n`Q5%OqtzT?#x6= zmZS)3RVpTymoHj_JX9#Y0z#D!e({5U!F;u|-TlNTznBP~b7yw@P@K)o-h1vj=id39 z-#KTTwzi}MSCBqG*xeyXf8b>9)dG{J;C4M(lBh&wTPn(?EaRBiq^OumQ8m?~W@ RB+Yq{x zEsbrK(dEKs8Q3hRD`MY~P1ih|l`Pe?)9EVOE$mi+T^GHJ$t>9=iF0Xyfkf{Xwi;ax zduQkxx^`5JcUR~-*!`aP1UkK!-X}b*6rR>Ec)Qt?ZlGDAw~F4sUCM5(V?45QpuT9i zURDWOw`|+`isO5X2Z>%*W+mzd+RHxUL!gw{&Ro}WN}!kA!SaROjBlYdXphIQFt_ZK zTo$y&f>+Bl?=djc2bh )rAa%-WvYv18ja`wFb=f!qDYCNJ{3DNiXZr+Mr# zS9B<|gG9U>5W2HK@Z|BO!av@>!tFi}kAt!&jms6eA`OxWa)49_UkwsPNK}w06@_ tjGAloI7t5l2RS-sCX1@!bE0Jqauuh+*eRgawtua0c(4X=Dx`{L_x zbbMy){LQH&;gPqh?|)PKc`_Usub(<|fdnbn%X_|?E5PXkoiZz86A@Y+Y!6XVesg(JtKt(v~G37!HEL8n!6%dFt#3U=Og za~93{rM*E*V-_rHtjEALG?KG(ZlI$S0G^A5S(T?j#@odXY#$KADh=dzIh
$RsJ>wnc{-0gqODpBVRw}0DEVRxPvw{d3>&Wdwyw^NFzkMz5H z?Ys?KDh}m# m7}ca^uwS(cJKC-hxiKcj`hTaQX-MzG*RWWtjY%dh*;g<-Xsvv zg?X(0JE&%5z6kz$>Hxgt-vy7_FCT?(eOW#9eeLYQC|ENeA8tf7O9C>$f)r(Lfm?!@ zd^s4+Bb)+)CgIk?WR`Fd-Q0GM%#w?$kZYR185ENlxZ+L6&R0jShyZ^WzIVEIV=VmS z^UT8!ZqD>MnWvqS$4Z`1=S#rwPkf2SA)B1x2u5F45qvO>=(TgUHL%+gk%bjJya=Y5 zaQ#97Qdk5kdUV5L&?)o*b;PVegQc+IBHm=!&=F>paD3A_Ap0V}{dFLXAr+Ys0bBj# zhwAambASzu23epg L4 *7HMS!MnOjHj} z-kcf Dk&Kk#bd#S_&_KRz)1)9LW?x7CxA_0K- X3B z{VRA_G(-)VnfNB61f+U1$)nH;%l|4B|6>`K2fhq84U(1{N0tgka11Q(#3elnU{>cC z!das5l{oD}l|-aM7g8o2$s1%@1G+9ID3B$Y2C^gx=BFVt6tk4ChsFJ!&HVHnFK_4e zVq@_a!&2?a_q7}E0Hn1`m&2crLG7zk5Z8Z$hmVe<>_9qwIvk!k*Hi<7uZHD-*o JKSr^J627DWJSA6yBK9*6P{c^ZzK zs7;6(JvLcA0(Il<`oxbA!RhNC;Eo#~s(v;RP7R0W-j9wd9ApXK2+lY*4;YK0oxo<8 zw{57i&9x{$H6QEdLZ}VYZxq5u!I6vULWVn90oEQE?qAx3)rCrJvk2Ea7c4x@!h*%q z74n}M2K^99*A_5|GGqKF=ui Qqyx)Ju4IVCGK2b5=EsZps~kbHm(=38I3JJ7wMGGM~-YavL) z{e@%g;m8M$gb32JEvU!gMUMEI>t}`Y`cjXJy^8fTBEl2s2R~(bD>}>E$quXD&OAgI zi>kTd&T3B6caG+r2p$9_(0TM_rj{Mo6CDq~DzIn=idFJNc@C7a?}=;+6u?LjM4&N; zRsu^=`CFcVFDu_>PhxL$Ux$YwbpnET<4=dy+ASMN9JSmgvT@r;8Hz5ee-oM9CWPD~ Yit%^Ha)YEnW4_c#>56(Q((AbO4? i zFE9&uES-X~Vm! z3YHD9T%wJ Z#`!Ysp5(H6Rzwocf_6{6h|e2T7NY9;(y8Gaq$yXDAYo32~3R}sJd zTkuyf`pOz=x5OW6wQT*y|FM3{k~1!j$AZ7s$gu2#YhCN+@fKVpuj~%6oJ+x1wI4cgBogBo z#A`a3C=;exUUfLepg}Ow^f4?Oh=jpTca-t@f5M=4n&!`v}8EBVm@|jZ(+4DDC4I zn5aI%a9+9}TIG2i?Y;12+<)}wq0YDcOq2uI(*`#uqPl%F4Z|iRA$mg*nhEk6X_%+z ze!oOM!G+k7XW@PE9EyVk38}(KbR>uYxusxE5JTh;F(A2L>Jq9l4d0=LDAXy#P|K~v zwt!JiP}y(=LouX4MowQIqDh*XP?Sf{kTP^b*=C`}=w;hJLWZKGRdSS@inmCYx+ic2 z&Ks+N`GreY@{=P6I`a3vDE?+Ve?IYKH2FEj>sijn#aOQ&JjttRhVuo2^P@27>uQ+v z `iu1%b7p zL9aCArI}E~4K`)wv8~ZTajz^FqnR*=nqVy~&};~bBJrO%G1t(NYuKJ?*gk2U?8>!u zXWF{64L?jPSIlVavyOE+$Igsn=Vbqv^||)GOnYC}aWt*9&*)dqTAPx4)7yKdti5SN z@2t5YXI`5zuTAtP>$B!9Y3-IdlRc?OZ|j;e?N4j>f5T$ZooWAW`}fGx=JE#JkO&ON z%>M(%TqLqV)jE&49& 0;Rv7AWDMa1^!?BwL?m-_u zrbssp8}s`?##sDwfeoOQQ1d3yyi8EE0Xp$gY%3H((En{9AYi7ZjHxL>CEm!I-0`j% zy>)g`$R6v>-v}%{v)(0-SxgYZSPKRdBP1lL7^lL=e=K~IlEsNPlsOOb>GMl}L6}Pr z*t3GrwL-{WDmv5 =Snxq!*gg?o^2 z&PoC3SO_H_yrUXYff!=C3(vqy&X8Dl5GDyUl3XsZZtmf=!tm{<4@UAAelPaVJxD+j zK|u01FBfjz-86Uq(|qa=g|XZ7zrNZN2{TV0yuUz3gs(>e_fQ?QTxx-T2;T(+@}U*D zRSyNP7HI$`_!_jpNrW>OIk1UFG@*sm$N5nqs5np|=w`591ur`ag-FmE!oD`wxFgfJ zV{*^r>1^X0X=OcDoy82**m4?2M&n3pHq1HK=bUXBXWQhFFAcff$1=N*Wu0%PwT>Bc zi=xy+L-(xJk+ZgBtSyN>NnNTtYi%FVOq=UQOtYpH3ptT8WKBEcUDJANyhjqR zJ+?iy )x}$>{9i5=E~Vya=$`)@6fx{MQ3`N! zd=k%pcB5hjIlUT&c`C>toL0P&JsF7ds$d`#;FeFB*TL*1QwHt_6J&*SkT!jUKp`r& z5kQ3C7k_y#f8itew}NoxM=lqyC9!;s-Y$Fq!u#I*wY!3qi$Ysq2HFY*w1r=)249AJ z!65tvD`TQIsbct-R{70|(qzEqk|40?H30fPyetmB7 D$6=x7#QTD*Pz$)Dd7vvRpKlN5d-!{qWV+$$DKyI$r$v>n#&gqM8<3ekNQLD$_G zlRHJFK-YIIqw5l-@%`h>hVPI)E(fpX2BY9fgq4ZcNY@F3Ef5xIgq4&xE!;R-BPfJ4 zxYNwyD+tqCi76IURD}yHXS^1xe!mZ>fUl0ch4w`%wqE!U1xC13sgZb9S4JbOcvC^^ z@Ek<|E-v^V#w(&R4q>t272pSfK7tcICtg4&AyQ1+2KVb&ka->LgFdXT>}4oR3X&ur z5%pgYn=-_vN5tx{h|Ubr`G~MTBGx}5R?TQEXMY-3KPENj?8EkvA18Ok?OAfi%(fkq z`|k8UBediJa%`X^)XA>rLj6KPP;Dg&50z>NN_);Z>`a@Rlm56fOKzRnusP{Z9Zv7< zpW5J`S+g;@@3+0r6jh`pvA0A(HSK75jz2NVt0f9rr8*4KINX>vIFsIZW0u_cOik1@ zjM)-oy0vf0c67$tFt+YP_cKi`X`8k-l@w4vHd{+7s7q?1%JLkKV8qu;6z*%SAg)fW zN&PIdwF|@U|EHz)qHnA{y>Zu+W%o>V-9>inRH85a+M%iH!<99v$m(gGu>^apeylf@ zR8UK6Knt${$A)cJ%eLK;>c#jSux(qTuv3)|c51Pe6i`3bnxEruJhzj4MnMx{0{<6J CTQbrB literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/api/advisors.py b/sqlalchemy_fastapi_demo/api/advisors.py new file mode 100644 index 0000000..2c5effc --- /dev/null +++ b/sqlalchemy_fastapi_demo/api/advisors.py @@ -0,0 +1,50 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +# 下面三行,坚决把前面的 sqlalchemy_fastapi_demo. 删掉! +from database import get_db +from scheme.advisors import AdvisorIn, AdvisorOut +from dao.advisor import service, crud + +router = APIRouter() +@router.get("/read",response_model=AdvisorOut) +def read_advisor(advisor_id:int|None=None,advisor_name:str|None=None,db:Session=Depends(get_db)): + r_advisor=crud.search_advisor(db=db,advisor_id=advisor_id,advisor_name=advisor_name) + if r_advisor is not None: + return r_advisor + raise HTTPException(status_code=404,detail="顾问老师不存在") +@router.get("/list",response_model=list[AdvisorOut]) +def list_advisor(advisor_name:str|None=None,db:Session=Depends(get_db)): + return crud.list_advisors(db=db,advisor_name=advisor_name) + # r_advisor=crud.list_advisors(db=db,advisor_name=advisor_name,phone=phone) + # if r_advisor: + # return r_advisor + # raise HTTPException(status_code=404,detail="顾问老师不存在") +@router.post("/create",response_model=AdvisorOut) +def create_advisor(advisor_in:AdvisorIn,db:Session=Depends(get_db)): + c_advisor,error=service.create_advisor(db=db,advisor_id=advisor_in.advisor_id,advisor_name=advisor_in.advisor_name) + if error == "DUPLICATE": + raise HTTPException(status_code=409, detail="该顾问ID已被占用") + if error is not None: + # 兜底:Service 新增了返回码但这里没接住,不要静默当成成功 + raise HTTPException(status_code=500, detail="未处理的业务结果: " + error) + return c_advisor + + +@router.put("/update",response_model=AdvisorOut) +def update_advisor(advisor_in:AdvisorIn,db:Session=Depends(get_db)): + u_advisor,error=service.update_advisor(db=db,advisor_id=advisor_in.advisor_id,advisor_in=advisor_in) + if error == "NOT_FOUND": + raise HTTPException(status_code=404,detail="更新失败:顾问不存在") + if error is not None: + raise HTTPException(status_code=500, detail="未处理的业务结果: " + error) + return u_advisor +@router.delete("/delete/{advisor_id}") +def delete_advisor(advisor_id:int,db:Session=Depends(get_db)): + d_advisor,error=service.delete_advisor(db=db,advisor_id=advisor_id) + if error == "NOT_FOUND": + raise HTTPException(status_code=404,detail="顾问老师不存在") + if error == "HAS_STUDENTS": + raise HTTPException(status_code=409, detail="顾问老师下还有学生") + if error is not None: + raise HTTPException(status_code=500, detail="未处理的业务结果: " + error) + return {"message":"删除成功","delete_id":d_advisor} \ No newline at end of file diff --git a/sqlalchemy_fastapi_demo/api/c_lass.py b/sqlalchemy_fastapi_demo/api/c_lass.py new file mode 100644 index 0000000..f505990 --- /dev/null +++ b/sqlalchemy_fastapi_demo/api/c_lass.py @@ -0,0 +1,73 @@ +# # api/c_lass.py +# # 本文件定义班级的所有 API 路由(Controller 层) + +from fastapi import APIRouter, Depends, HTTPException, Query +# APIRouter=创建路由,Depends=依赖注入,HTTPException=错误响应,Query=查询参数校验 +from sqlalchemy.orm import Session # 会话类型 +from database import get_db # 导入会话生成器 +from dao.c_lass import create_c_lass, get_c_lass, get_all_c_lass, update_c_lass, delete_c_lass +# 把DAO层的5个函数都导入进来,接口里直接调用 +from scheme.c_lass import ClassCreate, ClassUpdate, ClassResponse +# 路由对象,具体前缀(/c_lass)在 main.py 统一注册 +router = APIRouter()# 创建本模块的路由对象,main.py会把它注册进应用 + + +# ---------- 1. 新增班级 POST ---------- +# 完整地址:POST /c_lass/add +@router.post("/add", response_model=ClassResponse, summary="新增班级") +# 装饰器:注册一个POST接口,路径/add;response_model=返回时按ClassResponse格式化 +def add_c_lass(class_data: ClassCreate, db: Session = Depends(get_db)): + # class_data: ClassCreate = FastAPI自动校验请求体并转成对象;db = FastAPI自动注入会话 + # 先查重:如果这个班级ID已经存在(包括逻辑删除的),进入if + if get_c_lass(db, class_data.class_id): + raise HTTPException(status_code=400, detail="该班级ID已存在,不能重复添加") + return create_c_lass(db, class_data)# 通过查重,调DAO层真正插入,返回结果 + + +# ---------- 2. 根据id查询单个班级 GET ---------- +# 完整地址:GET /c_lass/{class_id} +@router.get("/{class_id}", response_model=ClassResponse, summary="根据id查询班级") +# GET接口,路径里带班级编号,如 GET /c_lass/101 +def get_class_by_id(class_id: int, db: Session = Depends(get_db)): # 调DAO查询 + db_class = get_c_lass(db, class_id) + if not db_class: + raise HTTPException(status_code=404, detail="该班级不存在") # 查不到就返回404,带提示信息 + return db_class + + +# ---------- 3. 分页查询所有班级 GET ---------- +# 完整地址:GET /c_lass/?skip=0&limit=10 +@router.get("/", response_model=list[ClassResponse], summary="分页查询班级列表") +# GET根路径,如 GET /c_lass/?skip=0&limit=10;response_model是列表 +def get_class_list( + skip: int = Query(0, ge=0, description="跳过的记录数"), # 查询参数skip,默认0,必须≥0 + limit: int = Query(10, ge=1, le=200, description="每页最大记录数"), # 查询参数limit,默认10,范围1~200 + db: Session = Depends(get_db), +): + return get_all_c_lass(db, skip, limit) # 调DAO分页查询 + + +# ---------- 4. 修改班级 PUT ---------- +# 完整地址:PUT /c_lass/{class_id} +@router.put("/{class_id}/", response_model=ClassResponse, summary="修改班级信息") +def update_class(class_id: int, update_data: ClassUpdate, db: Session = Depends(get_db)): +# def update_class(class_id: int, start_time: date, db: Session = Depends(get_db)): + + if not get_c_lass(db, class_id): # 先确认要改的班级存在(存在且没删) + raise HTTPException(status_code=404, detail="要修改的班级不存在") + return update_c_lass(db, class_id, update_data) # 调DAO执行局部更新 + + +# ---------- 5. 删除班级 DELETE ---------- +# 完整地址:DELETE /c_lass/{class_id} +@router.delete("/{class_id}", summary="删除班级") +def delete_class(class_id: int, db: Session = Depends(get_db)): + if not delete_c_lass(db, class_id): + raise HTTPException(status_code=404, detail="该班级不存在") + # 删除失败(查不到)返回404 + return {"message": "删除成功"} + + + + +#API 层只做三件事—— 接请求、校验 / 查重、调 DAO,自己不写 SQL \ No newline at end of file diff --git a/sqlalchemy_fastapi_demo/api/employment_api.py b/sqlalchemy_fastapi_demo/api/employment_api.py new file mode 100644 index 0000000..3eed738 --- /dev/null +++ b/sqlalchemy_fastapi_demo/api/employment_api.py @@ -0,0 +1,127 @@ +# api/employment_api.py +# 本文件定义学生就业信息相关的所有 API 路由(Controller 层) +from typing import List, Optional + +from fastapi import APIRouter, Depends, HTTPException, Query +from sqlalchemy.orm import Session + +# 注意:下面的导入全部去掉了 sqlalchemy_fastapi_demo. 前缀! +from database import get_db +from dao.employment import EmploymentBaseDAO, EmploymentOfferDAO +from model.employment import EmploymentBase, EmploymentOffer +from scheme.employment import ( + EmploymentOfferUpdate, + EmploymentBaseUpdate, + EmploymentBaseCreate, + EmploymentOfferCreate, + EmploymentQuery, + EmploymentOfferQueryResponse, + EmploymentBaseQueryResponse +) + +router = APIRouter() + +#-----------多条件查询就业协议信息----------- +@router.get("/offer/search/",response_model=List[EmploymentOfferQueryResponse],summary="多条件查询就业协议信息") +def search_offer( + stu_id: Optional[int] = Query(None, description="学生学号"), + offer_id: Optional[int] = Query(None, description="offer编号,需同时提供学生编号"), + skip: int = Query(0, ge=0, description="跳过的记录条数"), + limit: int = Query(10, ge=1, le=200, description="返回最大记录数"), + db: Session = Depends(get_db) +): + #捕获异常 + try: + data_list = EmploymentOfferDAO.different_choice_query( + db=db, stu_id=stu_id, offer_id=offer_id, skip=skip, limit=limit + ) + except ValueError as e: + raise HTTPException(status_code=400, detail=str(e)) + return data_list +#-----------多条件查询就业基础信息----------- +@router.get("/base/search/",response_model=List[EmploymentBaseQueryResponse],summary="多条件查询就业基础信息") +def search_base( + query: EmploymentQuery = Depends(), + skip: int = Query(0, ge=0, description="跳过的记录条数"), + limit: int = Query(10, ge=1, le=200, description="返回最大记录数"), + db: Session = Depends(get_db) +): + # 多条件筛选就业基础信息 + 分页 + if query.min_salary is not None and query.max_salary is not None and query.min_salary > query.max_salary: + raise HTTPException(status_code=400, detail="最低薪资不能大于最高薪资") + + data_list = EmploymentBaseDAO.different_choice_query( + db=db, + stu_id=query.stu_id, + company_name=query.company_name, + min_salary=query.min_salary, + max_salary=query.max_salary, + skip=skip, + limit=limit + ) + return data_list +#-----------添加就业基础信息----------- +@router.post("/base/add/",response_model=EmploymentBaseQueryResponse,summary="添加就业基础信息") +def add_base(obj: EmploymentBaseCreate, db: Session = Depends(get_db)): + items = EmploymentBaseDAO.get_by_stu_id(db, obj.stu_id) + if items: + raise HTTPException(status_code=400, detail="该学生的就业基础信息已存在,不可重复新增") + + new_obj = EmploymentBase( + stu_id=obj.stu_id, + employment_open_time=obj.employment_open_time, + job_time=obj.job_time, + company_name=obj.company_name, + salary=obj.salary, + is_deleted=0 + ) + res = EmploymentBaseDAO.create(db, new_obj) + return res +#-----------添加就业协议信息----------- +@router.post("/offer/add/",response_model=EmploymentOfferQueryResponse,summary="添加就业协议信息") +def add_offer(obj: EmploymentOfferCreate, db: Session = Depends(get_db)): + new_obj = EmploymentOffer( + stu_id=obj.stu_id, + offer_id=obj.offer_id, + offer_time=obj.offer_time, + is_deleted=0 + ) + res = EmploymentOfferDAO.create(db, new_obj) + return res +#-----------修改就业基础信息----------- +@router.put("/base/{stu_id}/",response_model=EmploymentBaseQueryResponse,summary="修改就业基础信息") +def update_base(stu_id: int, obj: EmploymentBaseUpdate, db: Session = Depends(get_db)): + update_data = obj.model_dump(exclude_unset=True) + try: + res = EmploymentBaseDAO.update(db, stu_id, update_data) + except ValueError as e: + raise HTTPException(status_code=400, detail=str(e)) + if not res: + raise HTTPException(status_code=404, detail="未找到该学生就业基础信息") + return res +#-----------修改就业协议信息----------- +@router.put("/offer/{offer_id}", response_model=EmploymentOfferQueryResponse,summary="修改就业协议信息") +def update_offer(stu_id:int,offer_id: int, obj: EmploymentOfferUpdate, db: Session = Depends(get_db)): + # offer 表主键是 (stu_id, offer_id),定位记录需要两者 + try: + res = EmploymentOfferDAO.update(db, stu_id, offer_id, obj.offer_time) + except ValueError as e: + # 捕获校验异常,返回标准400错误给前端 + raise HTTPException(status_code=400, detail=str(e)) + if not res: + raise HTTPException(status_code=404, detail="未找到该就业协议记录") + return res +#-----------逻辑删除就业基础信息----------- +@router.delete("/base/{stu_id}/",summary="删除就业基础信息") +def delete_base(stu_id: int, db: Session = Depends(get_db)): + ok = EmploymentBaseDAO.delete(db, stu_id) + if not ok: + raise HTTPException(status_code=404, detail="记录不存在或已经删除") + return {"code": 200, "msg": "删除成功"} +#-----------逻辑删除就业协议信息----------- +@router.delete("/offer/{stu_id}/{offer_id}",summary="修改就业协议信息") +def delete_offer(stu_id: int, offer_id: int, db: Session = Depends(get_db)): + ok = EmploymentOfferDAO.delete(db, stu_id, offer_id) + if not ok: + raise HTTPException(status_code=404, detail="记录不存在或已经删除") + return {"code": 200, "msg": "删除成功"} diff --git a/sqlalchemy_fastapi_demo/api/statistics.py b/sqlalchemy_fastapi_demo/api/statistics.py new file mode 100644 index 0000000..998ffb6 --- /dev/null +++ b/sqlalchemy_fastapi_demo/api/statistics.py @@ -0,0 +1,106 @@ +from fastapi import APIRouter, Depends, HTTPException, Query +from sqlalchemy.orm import Session +from sqlalchemy import func + +# 注意下面这些导入,全都没有 sqlalchemy_fastapi_demo. 前缀! +from scheme.statistics import StudentAge, ClassCount, ScoreCount, ScoreAvg, Employment, EmploymentOff +from database import get_db +from model.students import Student +from model.Score import Score +from model.employment import EmploymentBase, EmploymentOffer +from model.c_lass import Classinfo +from dao.statistics import ( + students_age, class_statistics, score_above, score_fail, + avg_scores, top_salary, stu_every, class_avg +) + +router = APIRouter() +# app = FastAPI(title="统计接口") # 这行如果不需要可以注释掉 + +# -动态年龄范围查询**:支持用户输入年龄阈值及比较条件(如大于、小于、等于、区间等),动态查询符合条件的学员信息。 +@router.get("/students/age") +def api_students_age(op: str = Query(..., description=">, <, =, >=, <=, between"), + age_value: int = Query(None),age_min: int = Query(None), + age_max: int = Query(None),db: Session = Depends(get_db)): + try: + rows = students_age(db, op, age_value, age_min, age_max) + except ValueError as e: + raise HTTPException(status_code=400, detail=str(e)) + return [{"stu_id": s.stu_id, + "stu_name": s.stu_name, + "age": s.age, + "gender": s.gender, + "class_id": s.class_id,} for s in rows] + +# 多维度班级统计**:统计每个班级的总人数,以及按性别(男、女)细分的人数分布。 +@router.get("/classes/statistics") +def api_class_statistics(db: Session = Depends(get_db)): + return class_statistics(db) + + +# - 查询每次考试成绩都在输入分数线(如80分)以上的学生的编号、姓名和成绩。 +@router.get("/scores/above") +def api_score_above( + score_input: int = Query(..., ge=0, le=100), + db: Session = Depends(get_db)): + rows = score_above(db, score_input) + return [{"stu_id": i[0], "stu_name": i[1], "exam_order": i[2], "score": i[3]} for i in rows] + +# - 查询有输入指定次数(如两次)以上不及格的学生的姓名、班级和不及格成绩明细。 +@router.get("/scores/fail") +def api_score_fail( + fail_times: int = Query(..., ge=1), + fail_score: int = Query(60, ge=0, le=100), + db: Session = Depends(get_db)): + rows = score_fail(db, fail_times, fail_score) + return [{"stu_name": i[0], "class_id": i[1], "exam_order": i[2], "score": i[3]} for i in rows] + +# 统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序 +@router.get("/scores/avg") +def api_avg_scores(order: str = Query("desc", pattern="^(asc|desc)$"), + db: Session = Depends(get_db)): + a = avg_scores(db, order) + return [{"exam_id": i.exam_id, + "class_id": i.class_id, + "avg_score": round(float(i.avg_score), 2)} for i in a] + +#就业统计 +# - 统计就业薪资排名 Top N(动态输入 N)的学生的姓名、班级、就业时间和就业公司。 +@router.get("/employment/top") +def api_top_salary(n: int = Query(5, ge=1), db: Session = Depends(get_db)): + return top_salary(db, n) + +# - 统计每个学生的就业时长(计算公式:offer下发时间 - 就业开放时间)。 +@router.get("/employment/every") +def api_stu_every(db: Session = Depends(get_db)): + return stu_every(db) + +# 每个班级的平均就业时长 +@router.get("/employment/class_avg") +def api_class_duration(db: Session = Depends(get_db)): + return class_avg(db) + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sqlalchemy_fastapi_demo/api/students.py b/sqlalchemy_fastapi_demo/api/students.py new file mode 100644 index 0000000..26398c8 --- /dev/null +++ b/sqlalchemy_fastapi_demo/api/students.py @@ -0,0 +1,108 @@ +# api/users.py +# 本文件定义学生相关的所有 API 路由(Controller 层) + +from fastapi import APIRouter, Depends, HTTPException, Query +from sqlalchemy.orm import Session +from typing import List, Optional + +# 注意下面这三行,坚决把开头 的 sqlalchemy_fastapi_demo. 删掉! +from database import get_db +from dao.students_dao import StudentDAO +from scheme.students import StudentCreate, StudentUpdate, StudentResponse +router = APIRouter(prefix="/students",tags=["学生信息管理模块"]) + +# 增加学生信息接口 +@router.post("/",response_model=StudentResponse) +def create_student_api( + student_in: StudentCreate, + db: Session = Depends(get_db) +): + # 1. 校验外键:班级和顾问是否存在(与更新逻辑保持一致) + if student_in.advisor_id is not None: + advisor_exists = StudentDAO.inspect_advisor_id_unq(db, student_in.advisor_id) + if not advisor_exists: + raise HTTPException(status_code=400, detail="该顾问不存在") + + if student_in.class_id is not None: + class_exists = StudentDAO.inspect_class_id_unq(db, student_in.class_id) + if not class_exists: + raise HTTPException(status_code=400, detail="该班级不存在") + + # 2. 校验通过后,直接调用 DAO 新增学生 + student = StudentDAO.create_student(db=db, obj_in=student_in) + return student + +# 查询所有学生接口 +@router.get("/all", response_model=List[StudentResponse]) +async def get_all_api( + skip: int = Query(0, ge=0, description="跳过的记录数"), + limit: int = Query(100, ge=1, le=200, description="返回的最大记录数"), + db: Session = Depends(get_db) # 依赖注入获得数据库会话 +): + students = StudentDAO.get_students_all(db, skip=skip, limit=limit) + return students # FastAPI 自动根据 response_model 转换为 JSON + +# 多条件查询接口 +@router.get("/search",response_model=List[StudentResponse]) +async def get_multi_condition_api( + stu_id: Optional[int] = Query(None, description="学生编号"), + stu_name: Optional[str] = Query(None, description="学生姓名(支持模糊查询)"), + class_id: Optional[int] = Query(None, description="班级编号"), + skip: int = 0, + limit: int = 100, + db: Session = Depends(get_db) +): + student = StudentDAO.query_multi_condition( + db = db, + stu_id = stu_id, + stu_name = stu_name, + class_id = class_id, + skip = skip, + limit = limit ) + return student + +# # 根据id查询单个学生接口 +# @router.get("/{stu_id}", response_model=StudentResponse) +# async def get_student_by_id_api( +# stu_id: int, +# db: Session = Depends(get_db) +# ): +# student = StudentDAO.get_student_by_id(db=db, stu_id=stu_id) +# if not student: +# raise HTTPException(status_code=404, detail="用户不存在") +# return student + +# 更改学生信息接口 +@router.put("/{stu_id}",response_model=StudentResponse) +async def update_student_api( + stu_id: int, + stu_update: StudentUpdate, + db: Session = Depends(get_db) +): + """更新学生信息,支持部分字段更新""" + # 检查学生是否存在 + existing = StudentDAO.get_student_by_id(db, stu_id) + if not existing: + raise HTTPException(status_code=404, detail="学生不存在") + # 校验外键(班级和顾问是否存在) + if stu_update.advisor_id is not None: + advisor_exists = StudentDAO.inspect_advisor_id_unq(db, stu_update.advisor_id) + if not advisor_exists: + raise HTTPException(status_code=400, detail="该顾问不存在") + if stu_update.class_id is not None: + class_exists = StudentDAO.inspect_class_id_unq(db, stu_update.class_id) + if not class_exists: + raise HTTPException(status_code=400, detail="该班级不存在") + # 直接调用 DAO 更新,学号不可改等逻辑已在 DAO 层处理 + student = StudentDAO.update_student(db = db , stu_id = stu_id , obj = stu_update) + return student + +# 逻辑删除接口:不返回完整学生实体,返回简单提示 +@router.delete("/{stu_id}",status_code=204) +async def delete_student_api( + stu_id: int, + db: Session = Depends(get_db) +): + StudentDAO.delete_student(db, stu_id) + # 返回 None 表示 204 状态码(无内容) + return None diff --git a/sqlalchemy_fastapi_demo/api/teachers.py b/sqlalchemy_fastapi_demo/api/teachers.py new file mode 100644 index 0000000..f02b9d7 --- /dev/null +++ b/sqlalchemy_fastapi_demo/api/teachers.py @@ -0,0 +1,81 @@ +from typing import List +from fastapi import APIRouter, Depends, Query, HTTPException +from sqlalchemy.orm import Session + +# 坚决把下面这三行开头的 sqlalchemy_fastapi_demo. 全删掉! +from scheme.teachers import TeacherAdd, TeacherResponse, TeacherUpdate +from database import get_db +from dao.teachers_dao import TeacherDAO +router=APIRouter() +# ---------- 创建新教师 ---------- +@router.post("/teacher/add",response_model=TeacherResponse) +async def add_teacher(teacher:TeacherAdd,db:Session=Depends(get_db)): + existing_foreign_key=TeacherDAO.inspect_class_id_unq(db,teacher.class_id) + if existing_foreign_key:# 外键校验 + existing_teacher_id=TeacherDAO.inspect_teacher_id_unq(db,teacher.teacher_id) + if existing_teacher_id:# 主键校验 + raise HTTPException(status_code=409, detail="主键教师ID已被占用,包括软删除") # 资源冲突 + return TeacherDAO.add_teacher(db,teacher) + else: + raise HTTPException(status_code=404, detail="班级ID不存在,数据库无数据,或已被软删除") # 关联资源不存在 +# ---------- 软删除教师 ---------- +@router.delete("/teacher/delete", status_code=204) +async def light_delete_teacher(teacher_id:int=Query(...,ge=1,description='输入想要删除的教师ID'), + db:Session=Depends(get_db)): + """ + 删除用户,成功返回 204 No Content + """ + success = TeacherDAO.delete_light(db, teacher_id) + if not success: # 目标删除教师ID不存在(被硬删除或软删除) + raise HTTPException(status_code=404, detail="教师ID不存在") # 关联资源不存在 + # 返回 None 表示目标教师ID已删除 + return None +# ---------- 更新教师信息 ---------- +@router.put("/teacher/update",response_model=TeacherResponse) +async def update_teacher( + teacher_data: TeacherUpdate, + teacher_id:int=Query(...,ge=1,description='输入教师想要更新的教师ID'), + db: Session = Depends(get_db) +): + """ + 更新用户信息(只更新传入的字段,也就是非None) + """ + # 检查教师ID是否存在 + existing_teacher_id = TeacherDAO.inspect_teacher_id_unq(db,teacher_id) + if (not existing_teacher_id) or (existing_teacher_id.is_deleted==1): + raise HTTPException(status_code=404, detail="教师ID不存在,已被硬删除或软删除") # 关联资源不存在 + # 更新班级ID + if teacher_data.class_id is not None: + # 校验外键,校验班级ID是否在Class表存在 + existing_foreign_key=TeacherDAO.inspect_class_id_unq(db,teacher_data.class_id) + if not existing_foreign_key: + raise HTTPException(status_code=404, detail="班级ID不存在,已被硬删除或软删除") # 关联资源不存在 + updated = TeacherDAO.update(db, teacher_id, teacher_data) + return updated + updated = TeacherDAO.update(db, teacher_id, teacher_data) + return updated +# ---------- 查询所有教师(分页) ---------- +@router.get("/teacher/total_query",response_model=List[TeacherResponse]) +async def get_teachers( + skip: int = Query(0, ge=0, description="跳过的记录数"), + limit: int = Query(100, ge=1, le=200, description="返回的最大记录数"), + db: Session = Depends(get_db) # 依赖注入获得数据库会话 +): + """ + 获取用户列表,支持分页,从skip+1条开始返回 + """ + users = TeacherDAO.get_all(db, skip=skip, limit=limit) + return users # FastAPI 自动根据 response_model 转换为 JSON +# ---------- 根据 ID 查询单个教师 ---------- +@router.get("/teacher/single_query", response_model=TeacherResponse) +async def get_teacher( + teacher_id: int, + db: Session = Depends(get_db) +): + """ + 根据用户 ID 获取详细信息,不显示软删除 + """ + teacher = TeacherDAO.inspect_teacher_id_unq(db, teacher_id) + if (not teacher) or teacher.is_deleted==1: + raise HTTPException(status_code=404, detail="教师ID不存在") # 关联资源不存在 + return teacher \ No newline at end of file diff --git a/sqlalchemy_fastapi_demo/dao/Score.py b/sqlalchemy_fastapi_demo/dao/Score.py new file mode 100644 index 0000000..d279d41 --- /dev/null +++ b/sqlalchemy_fastapi_demo/dao/Score.py @@ -0,0 +1,56 @@ +from model.Score import Score +from model.students import Student +from sqlalchemy.orm import Session +from scheme.Score import ScoreCreate,ScoreUpdate + +class ScoreDAO: + """用户数据访问对象,所有方法均为静态方法,方便调用""" + + @staticmethod + def inspect_stu_id_unq(db:Session,stu_id:int): + return db.query(Student).filter(Student.stu_id == stu_id,Student.is_deleted==0).first() + + + # 查所有数据 + @staticmethod + def get_all(db:Session,skip:int=0,limit:int=100): + return db.query(Score).offset(skip).limit(limit).all() + + # 查询单个数据 + @staticmethod + def get_by_id(db:Session,stu_id:int,exam_id:int): + return db.query(Score).filter(Score.stu_id == stu_id,Score.exam_id==exam_id).first() + + # 添加数据 + @staticmethod + def post_score(db:Session,score_create:ScoreCreate): + # 将 Pydantic 模型转为字典,并解包构建 SQLAlchemy 模型实例 + db_score=Score(**score_create.model_dump()) + db.add(db_score) #添加到会话 + db.commit() #提交事务,此时会执行 INSERT,并自动填充自增字段 + db.refresh(db_score) #刷新对象,获取数据库生成的默认值(如 created_at) + return db_score + + # 更改数据 + @staticmethod + def put_score(db:Session,score_id:int,exam_id:int,score_update:ScoreUpdate): + db_score=ScoreDAO.get_by_id(db,score_id,exam_id) + if not db_score: + return None + # 只更新客户端显式传入的字段(exclude_unset=True 排除未设置的字段) + put_score_data = score_update.model_dump(exclude_unset=True) + for k,v in put_score_data.items(): + setattr(db_score,k,v) # 动态设置属性 + db.commit() + db.refresh(db_score) + return db_score + + # 删除 + @staticmethod + def delete_score(db:Session,score_id:int,exam_id:int): + db_score=ScoreDAO.get_by_id(db,score_id,exam_id) + if not db_score: + return False + db.delete(db_score) + db.commit() + return True diff --git a/sqlalchemy_fastapi_demo/dao/__init__.py b/sqlalchemy_fastapi_demo/dao/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sqlalchemy_fastapi_demo/dao/__pycache__/Score.cpython-310.pyc b/sqlalchemy_fastapi_demo/dao/__pycache__/Score.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6ffff66e5e85b30dca145d1877153575ea4f533f GIT binary patch literal 2291 zcma)7&2Jnv6d!v&ceA@m(+1Ksf|4Sn0Tc-?NC=^#RE1NhloX`ZqS0pUC6mnTZ0uQR zqKQ GV%qD4qlN+b@1Lnz_^L5QCCCw!${niB_ZoOsW(AKCCBEcwl|-?ROGKR>@o z%H^T~?OA7k?HA85e#OD@X2Reiba@#BGZ=}Cm{bWtoklb^tESe?$cpW%t#vDMVz=tX zUezPU>jtx#bHiZH4y_iLyJYy@5$t97MA=J?L~u~trL@C%E7dBOGE7=NRb$$`Ab36H zy}{KsgFyq=A8!R1T!b#a2EmOgVMdiQQZ>27D7Tr(ou o-T)|4(Qf3vss?f8H^CIju!A|MfvEJ+?>;(SoG%qzhc7{!9YkAZP=RC$9 z*Om&K1}0{dr!ii7?aj^`5c+SQe%1Zx`|j;~-CGBb4(=a)cJT0U7C_LGb8KxwHSQ&=&rqIK#+7%5b*RJWp8x2*c6x(%4vpC%7sAc zRWXzS;}K6eQ+6{HGWDr|bTYJg-w+kh|6E>pxpq}@A!~1kEtb45YgaZKt921y5y={F zq&QAjlU8r|QcZ3|^{BDR !e=+ps#w;Rc=72FCOU zLY<>q=lTTC|J_gHI%43cEV&-Gl^um~m^Kh#zoCwO0lJ(4F=Q-5-pq`Gw2-NNvgq3a z-;=<@m6J4^lBePf4$OKK`DRYaX>`F^%}XxE(aC+6rvW(PK;j-VbZcS&pl4JrzgCa& zW>3cXKW;Xo!z1=wkeQKk!XVSn|p@-TD=*XCn?4S z{A=oqaRT`muuj|t<{48?BZ=W^l`D8taJkxtbq*FOkF5kcx|8=&Y$p;D3j;?&B;M_$ zStK4Q5{qn|9>5&>DKEzvvOeNYUb8G%+i& 9C`;zfau|~I@Z8rt4%*osxsJ|OizzRH8&5Dy*nkNfbF&CGiq?Y-$Mg;X0 zo(80&?+O=A6qw6m7KF0Hl*dxJV63O95Ko}xNf5r5=j$9!=#034+IbMwO1slzCV-M$ zS7cq0_fGOx7&zfVISHadEugMMCrG7F<1kwW?jxy<%njIj9tI<9nVAV}5nu~*#5|rO z3^T)Ayu9pNL(Iy_E0u-`23@9x2+za*Ct;NG6?r1O01mPQB1eMB0I4uFNQL9Ri% xIw^@22Ml8OT$LYp(ZkcBq%d%rD6g% zoJOIq5SbBAp>R<6D4s(xe5YE&nxa`iH;EVT85W`R459W6q1H5X& 6fT=a|T z!oL*ZdHurXHSGM&J@en5P@eG@FZ16=W#~Mgh&YG$^l);d;Ll6^3Gm)w8nDKy^Y|ZN XD({t?+*gr&{c1}_iIm6$nWTRK;o~w~ literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/dao/__pycache__/Score.cpython-312.pyc b/sqlalchemy_fastapi_demo/dao/__pycache__/Score.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d69e92d437851113cbacae56cbb024bd606dfbb GIT binary patch literal 3555 zcmbtXU2GiH6~6Pk U8`yF17KGQm5~rQN*WA(AVG+qK2_>VR-1Ois1cExY?Hp!#GpR(rRUt4 z{WHdG#g%;Sx#xWM&dmAFIeY!5&dxA_(NA9=`%oj~Z@8!pIZ!sf2g(wmgbEhP2nj(z zU9`lEl#sYCS#m~6C|s8 ~Cro)i7k5^d9=n06Z%F~L(t%&g5o z35~dU$|hW{GRH}0Ct{-4&fQ0CmULOLIGLlcF#W@P*%mA|{s77nVI(0?k`SqokeEzG zrcjBgDVfUi^0@$-2!SWUeF{^l3VxM_=9Ri%YwV;N_qH|dZVS9&7KU@%n>_7-rvpxf zeYBHxq%_*qgy?KVz;pE`Z`bsWShuI~?>=_q`}q^_!he5ZwOV|;`r=ykR~K$wc>ng& zg`00&y7lHO|9tm!bz!c0W}*7hrRwiry!rAkZd`ol_RGJi&i&lCAmF7-H{N^y*4lG$ zh$qrfPj%e9k)~!q2ag95Ey3SL5yTQHkTHSVTZCKRaW3$VDJ=lLXrRW_&wC5P_+CQl z`)kBC0c!+|kh8*YO!1V-JhP{5d_zx7r7f4)b~`SVRN8jjm}q1Ea+8BE*w^>jQ!vF( zI?Q(BX_NglJrO^~oN+gsi&x)zuKL@ho4
Ac;ogHJQ8+RtHq-CCB znQ0?%8I)zRahlA=IUPf}X|Fpy;p6~q_)#?S6O%K$YGe(4-icr641t&<*Y(KrQwvjP zLS? +9>YBM1pS%UlCsGdt?h3@kcg;~*L#RDSuhiat=%2UciV|3*dMSJL;b4V3kV zD*AzvexR%$x~v_tqj+wZO(io%)~3vE2_dE~58-)GzFY|Zmy~b9K$qP-3L-Cypuom3 zzc-CWS@@w=8= gHM =50h`zs30*sd`?pBxmJ`Gg5)+5d zVq)V9dErc!GRvU(Ob$|-QcpFr8K_M!WV4jboKv;1e+AJR9W{6WT4Nv1WgTcA7@3)9 zJ@^e{FYI+51u;iHRY~{GQslwq-Id-4O1%%1d-ubts9n{<Mb+aq5b8H|lK*ZKvB& z2`_{fAG)ILzN+sm>OKdW&q11c0ULS$_fv)^)JC0+e}DzpsM*O@JQRQ*h*H4NtXz;C zVVV@At@xnA`FaDHRSL>>j2t6B?k40%Py@5-Y{;#1Q;-X4Ayj*wKu-6_$Sr2}rqRMJ zHl$6XAlI51urC9*((sdT-RNXfrUiEo=;hF`Vj&wJZSO|W2f|a*F3UJx2%JgRwe7E= zryoR2^E=ueH1N_JMD0EhURN$3kZizpCFu#{p70X~OCLHOAAZ|wtK*s~v2MesI2MRG zawF1PiS(Bu{VU&DnOX~%BaaldkMx~aqdTwn4*2PD(Y=g0a;(^OHF|F)I#`Mh{v{e) zI9fbXO#Zbax_Dyw2g{Rx?znedB0XQfzJ1 +kMg1$hFb~t^4k !Q138|$$ZiZJR!rNSrg50 zD{<3ihPkJ*)W#;~N$CmKhT <0@o8aFuq z1~E@Ql7DzziL8r)^0=`4>^i}Db>t48HzcBV`>ypcsGk7p@Zz@-ba+ML)9O)#9 g`k0w=bmSs?l`h(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o11}*(xTqIJKxa zCOk7QCBM8lCZIAoBe5tqpeR2pHMs=DFUiQygK{lmiVJfRbCNSsb1UQ15{pX`3o_$V pQgicTQWEoH;^Q;(GE3s)^$IF)aoFVMr Dpyab}rCQODrx)EXdR?D9X=DO)k+dF3d^HNzO>k zt&E3C#iyj^=If^<=Ih7DXXa&=#K-FuRNmsS$<0qG%}KQ@Vg*{n2*kx8#z$sGM#ds$ GAPWFF3N_gP literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/dao/__pycache__/c_lass.cpython-310.pyc b/sqlalchemy_fastapi_demo/dao/__pycache__/c_lass.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e12ff5679bf06426a266b938577d7e385d0147b GIT binary patch literal 1703 zcmZ`(O>ZMb5S{Lx8ILEn<79WkCP;u*%ZE8c+*U#eAq8 e3&O}(eCwq&XjCH8}1EVpC>Ck^?~pS5td?a%A}Jdtg=^D^o-Z{OTiG2Xf-@8hl3 ztv6NM@IH`x@V4b!CqZZb8kq+j=4vO(n7kTeTR$o??8n2Z!`+rQj p*YA{NwcK)8463+VsB5$Flm#^q$TJ=b0{_>T0A0mTY@ojo0Rrp1CZt zVsNg?S$~)zl}X;0s;qi4t9pYzC3!fRx#qw#)?axV_>-X|+brb?OIgVD4osi8i?y;- zJ>FoA7>qDHYmcx2H-TkKw&0eH#GGBw8cM87zKE8=N${E 2qb*2=-tbf E7<~_+otnOnWmV$`w4*d!Tn&dt zS^YK{A}flU`W{dSc~=-b8V{sJKoGbF^DaURDI(zw)&>~;4h)x0y|76g8xU$ZysgF8 zFrZ*)_yxa$ZbwWq$zQRna2_uBGWat1KJD?V=qk2iF6PlZet|pSa(hGD!mC|C+v4~c zI dR>fW^=1b<7zn0tkt@S0F5h&IP%)|^&?;|fxvyU zxUDrHv}@+Xg_^nO$E<)f{#EDZI&LM_5AhL0pH6v0v_%W$_JaKgt__V+X=xl`n8%oI zdEs+z>XMz{7M$}w19mWjn~o5N$6sBOOrN1@1k=~l Ypuv{*p)s@#iC_|xpd8oRxn?hWxpa1~ z?ZE~v7&HaJJP65?Mv&T)7K%^plYf9OJuZ52saQ}8eLIPL_xqjO%_TL>gAVL`zw`Zm zXLjcE{my58jK^aH+W6Pkb64Vo{EmaLMFM5>Q&5(PNla>!Je{Nzb;*|U@}w+u*;exE zq?*?zH5e<5nkrMXim5FqlMykFuqce9Fm5sT2}=u$nlZ3yroNy~#= Qi}gZhy%<~UYi2Go`_b{h1VY{8IxT@21}mUdY%n3y$jAek3@xo{zu zk%DufP~el{+q?zcGI1#g(L9>l9@n(ujHlWyx)#LFNgm0CxNVE_q_tpWN+6 N#z8E4dU~FG2r@b0FzzI+47*~@BnO!@?G|Q}kG}up(O1iV z-oF0Fz13tk4ZoeWUZ3TK9Lu;#=aQYaGgB;IN(HWz$?}DynJy$VDco!SY{`#jM0!#U z3*Qg_8ida|0bQ9qhq^zP~)O3DX;=-aW;O;9f@fw~~w#8qM8Gc9^J~8v2^D8I{wT)==~4^ecpH z&EF%*W8@|sHB?`{RAjs)vgK=8%XS$TS@YGb#U0m>8X3YwI=I1}9=;ERAG^rh5WRz7 z7{P!ypevINJ^sbOwSh0sRrT(g-doXozqM*d2P#Jg?w+k29jxl_*7V_uK3vsD?kgia zfy*h*v^DFiwgu&p!3qc)>f&}Rfb##K^XL{Zd)|+|?#3A5ov;x@< c?vO@rr)@PH$BosOcvw`pK$( z>b`QS0bi^r2nO%Z4)m}@1bXYB?BEsxXoQR*d$L1I#FKK{k%t-BOnPgJIp!2k*{vu; z<`^U&LpDExb?4MM&D}!TlReeb)`Hb3`Mgv4uN)+YIRuuHfrI4Hap2!LyPC0!CQB7( zAQQkoSdxA$Uoe@SGK+aAEz4zj$B%$J?Yf-9OG9`YbVj6E;rs=h76l>_q~_}ZtU%sr zU!G 5j02bxT*w+jg1MdDc2kMYz-+;3|> z2mJ+}=lEy;<)(4R8__T7r9a4_f}y?73U%;_VPPy1HOI>)UJ_rnW?X>-$Ggq38aN*3 zCJ~!#luYy_{H|!TQ~XVE;e+7JLsyq6rB6Ic=#gK^JHL_h^{7e{OBd?|#Om-Sih6?5 zQM&YYouFLJYzp~TjMCFfSI~HRH6z3w;W}N9#b_rk0pdo75O b%7 literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/dao/__pycache__/employment.cpython-310.pyc b/sqlalchemy_fastapi_demo/dao/__pycache__/employment.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2909daf09da89f17b9b6a665a7dff7d7da0a463f GIT binary patch literal 4525 zcma)ATaO$^74ELC?&;~dcx|t*iU{Duc(^Q10zon%EI2kiIhJfdj8?S9Q$2C-_RMUm zd%zpDB@-LT1e+Ks*ntFj7de0t!2uy0Vq?GXEBck4wU-y3c!&*w?^N~d%w9nBs%olE zUApRg=X~e%b}JRnz;o?yznuQdF2ndMbw(cxok^5fpb~~KBcpBBO_SOzVr{E#skRmI zwq3W|PTf&`9u?Yd-E9}^Mb)<>uU)E_Oyetta75vpAqr<%y^NkKis%*5s|fFyQ7bLu zO-9YkDqlT*{OF-m&0sbOyB!D$$AUPfCd+uEBm9g%*GK~Ns)yRMQFpE#bdoPO;vm~J z>_6XX1yZd|dIIB3+I;jGLuV2to<|iJbyFC17FfazxL|?Z;=&UA96xK;oxm#E`JYoP zh#iAD!VL 8f|TWR 7L3y@Wq1)gB2BEQ6*Bw9ULfZrZIn5!FiHX`IXbdL5-*H> z5kx@}h|F$ s*0mTS5u|A1TUU!1@6=sN99tXijUy-XL#%FS+jw$YjMJB@abdF`;{$Bn2V z=g@AP8nk&l6V7IK6t=^pS-`r%Q$&OMO8eK)7}35t4Fj8j#!nYg7+lYkJJJGB$uUuK zrsNYTo3|I>YcrOd$mclo1!1M^4MSKzvlf6ScCpm#1NjU$wPtK3=SqHfMb2mR{K9-O z#f*6`bx@apyPLYeoofwb#sl;5T3MEHZUw!pP>VFGfwkjAhO=@z1R0OQnE)23mE&|< ztvE>JZW^*0QB*4q4MHuDJ7}AoRDp5~HB-GQgSo`LC{f0utF5%lb`g>r!+rhc$!^#T zd}Wj5x-p$#d)eh<<~ZBUTs8){(YCnx(!TXzZ@f`vbx%yMa~&HyEAWn^u^PM-04mqv z3PuGHIZnJgaRejAxX4~Mu?FxifGp8+7Yy}V%q1q2ZEIzRm*8r>XYiK(+rPN?+SSE( zFZSPlz5nK~md;=9-~9dZnOpbo{HT9^e)%WY{(k!cM(>~f^U}>*{a5Du@BD7@-JdSr zU0C|=4e($I9+LE8zu6VQLj*}9jB1_+kvu|!NPer4+(a#64B#Y0=D^@##aTfHEdX({ zmV5GJm{Bjlv4}v|V&gPr02bblIWa-%aSsTv+~LY5^*j@3>|BqAUYeD9vjSWAs2WWo zt-(W_LsX+sxQs?(%tNctAUkcPR_qDm7(!CYzHP{@DHG-{Bei@cfCMCuK*E&7B6or0 zaY!sB;esm(+)HpJu~TcBpXR9T({{?`WNK4M`HUeafhw3>Bbws~7gNYuz|lFP?fOw1 zF&iK9lHZ*TI(`y@KHTZ<3DxR-43p4Vy7I^6D}TtrymEc >^B!gGj4 z 0Vf_6{^T~Ss%^?# zUj+f*&ph96cSSD>&@TJnp+-dEfqLY8VY3||fC))voLM3Kg}}=!&?Vwy)NLek4+NT1 zDJExJgv~^LnuJeKMS*gpA_7zwrdSd`i^??^xQ;oDGjs6A-$(1;jIj?G0v$&F$!zuz za~`ll`F-{w%&+WZY}Zbv_G)6ARS#)r5+!~G)%q+*Sb>8Kg$rBdB85Cdaggs6P~4!{ zLK-JLHR`P%#k!Ixs}bZp#R~qa#Z6*dWlw`0#<0ugz-@VAi`c5Nrn0C2^=;XfA#JE! z4hfGk@5}~g`%mbfCs)x1>7L3#y3l7(fv$~|O`C9KF9A*Du57K4GtZsc9wBFT 91rd3PD$KZ8<4BnCVIAF4Fbnnq+p z%EIOgNEV#biT5V1u#_s1%piq%I<-<~x(Fpdg%M=T;7cpDeGj`K!BEk!Oi2e?l*`&Z zibRWdf4lVBpVY~<&-EzWEWP>brSISApMU56jkk1A%-Qkkd-oR3=zu4`fQhw=Jb)kV zRBN)8HGxinp}3ROGlEEAgfEHol=`xgPF?*dgzqW_EuBEZ?Q8K`)Rg~Xts=}SSA=PL ziXQV=XltT$O`=Ujm>c1lGbWku;33>ru%kG;3OkB}8aqp2hwqh?k8mefnx^wB9gijx zhc(C1mc*( mDc|r`nA!s=0QAW{0_8lWseB$Z}WW z#VK@PO@oh^VHyn^Rf+Cnsl6(Vwh`Ycz21|{(N}4=-6^XThTNae*iV_8vRNBh8`-{_ za@0j_?a-o?+b3C%j@$i a-z;5y>;8?OEA8I9eYyYYO(bdkyWd-0xYfUO0nD-V z>ZQdyZ)hvl69zdM-EB=`EtLT(Q~fZFQWh;gf~vO8N>}I3@}o3!7(7(m*aO+?C@}@0 z?H*;xlp(V-lqHWda7t|hPT4p~Mg$%~3x4+`z3?fjh-2kvsUo|T>ROb$N#Zj3G*txY zNRXq0jT}}TTb-DUFhGe(1&DMEQLFd}e(>uJA|8LZKH7~vR0e#cR?Q0er=m`6tHW=| ziLPwx$m|V;`eT;Pm+c!$SAA|yAmj(p1X8E`zYIEj(>?2Z|M!|aYmTMLzg0G;{A>u+ e%H1>f8J$`@OL>m|dNs=Um>Dz6W|eLE)_(w2k4rWH literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/dao/__pycache__/employment.cpython-312.pyc b/sqlalchemy_fastapi_demo/dao/__pycache__/employment.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f92ffd7c52fd276fbb3cdca623b245bafde789e9 GIT binary patch literal 7213 zcmds6X>1$U5q{(zyjJ2NS%;-qqHG 9kQ1Y^j6`u#s6| oyGRiOjnnv7X{m+(cINFx zN_3($Kz?*>zH4UZ?as`b`DXQ(x;ig`YyS)HB`-A+@(-Mt7i$bQzXyXQA`;P&B5B8j z!+~RG%9&;+m^3@V(m9jj() !uHTvC)oW;){3*x0lf)z}lUtOT?A(ez9zGnba8v&UkJr1|annaN2>j_W( 2 zEPZ70C*9_n-RB%reT3LDlhng(I*vrjWBP%$Yh5)L&P-)rbmpAn 8x87x>tj$(7(ws2fUkv3Hk2w zL K~T~2gP9RY_q@Rhp>TLi!~>EFI4GCAijh{*hsF`vTh;c1v1yp pbEPRYuN85sp?Y$`D&L73Csl+R2~DpFQ%LlP59r6L~tgwq@378KKp z4ZIwooOCA*&c8C7$|@dMhV!pqG9*BvHHisKDv)fV@$(so22mPl=KHoE+1i}=0?NOj zfwS8}f(=XVMfY2K3W2_2U{DPVeo$W=I;9Ss`t#H3&{!dGCeOjS6hiC1`$~ Z@nTKaM_#-HY;_Qm#Pu@Kx_ z3`W#oWVO2x94ZD6s= y1`VHuULtGJSc7KiTjVSnXV9#W4R%A<-*Q#iEx3gU)0`Cy!Lkel z27XLGyI~+|o|iK6R5YH*&S{NyLXBo-r0Hlj0eQ=v%$%bmIQ)2+WsFO<0Qmq;hp{<` z&3 S#EKzY#c-#f5-=DT{-E2fmOtneNDoAL8=9BNzu}m`>A>u~7Fv6*5FE+# zfAjAuH8huet;^q6eSM{_2Ue%mu1E4GZwMVFU&EE3sJ^aJd+(}SZGSL-^7YdtU(@n_ z)z@9>=wE$U?Kpyr?Kgel6}Wq-)PHFG@Kb94X I+T{ wRgGqnsEI9?9mr~7lbqAq`%A#`IFXSWan;PLT|m-v;a(V-xY){&)mCsL zE=?tr?ELQSQPHGffvAi^L*Z&5^u~pS3vbmI{Jlm0fa)LE0#6xd!23^cV4>$q HMq|kX$i#|? zcve1y^Y38uFf>;QeJbjiy8oi-@E)ZL-1-tJaltanaZSs;Wdhym@CJ699N|NBy)59! zP1-t2o%@XcEv=>2wmbfIuBjAgE;G>IY-}!b&_mK~+f#Po$W2=Jls!1|;>d?1fiyIg z>u^+08k;vzg0T~>jnF+=uHnj&GJ$So&jxk|2aNP*VMAOKazM9ooOWyC2F?sd7?t~} zD4uIXM(9?KZ(wI|z^EJmjyo*F^ 8hr@oo9k2q->5>j za(}W$=-F16*D8{nJFeZ0cS!C$3}K4U;k^$>r?8<30AWF-qCBUh>M-Ot%41W7^Ih9j zZI;j`PYlG`MYIu>`~`ns(LbpA2R{+oib9tvbgfLP!u@o%PZjn-Iu?fLtVb1kR-wk; zzv*HF-n(w%3oLYB?k#&*Pe@N8mcC&pt02}r`5W2MN~U(o`S!lFY)Kxr)mStbH669u zUbLD4rE#?qO4ArS-+6Bv>EA)HBv77&rZR6-S}5>lM={u|276ZztHB39c&s>lS{**U z{`52I@G}Krd{a*)bqjkhcVp@Z=uxHzBv!#4^i_JszTFx`#!^9!VDkVpRSLpPGv8W6 zL3*X}BHo1M27M#VtNS!U-Z+}Uybzev7kdo`JHc^)ACMoei)@ZXB$s1y?9P!KxV0Iw zbuqNfu_h`35YGaLcg~_meD=rRe*Wf%^wGy6oQ#H+zl#kbw+bxI*+Ei|3Y1O(IldqQ zavhP=q+C;LIv$?`Zsl=k01>)LXkRfntOkeIj$Pxgy9>cn79wx&p_uTi5VN5vkVlB6 z=}DM;O-<{?8e-;(@@yxVc@`rh)!*%x|M0~}i?{MCw}1ZbNg3-71k$!f>51GA%T AY2Zu0&0Zr+FnG>Ap>5*2=Fc9XNC(Pu7(bAHFO3C zi~toQM+MsLsEu|#I@*N}Au4oh!?e48a06$CL>QHus6>|zdZ9yp=+@xjpfea@R1Q(> z%j(z{I%I?nu`hI#@eVwhUeM6PIu`M2_4Z#41~PJ5FHF4lqW)J5)T`EKuU7qmVE`%~ zDK#Kje`3(97itv@&w5~}HiPCK(d(o~<+H$owYbs^O_^~x9DgTWpOWyWWc)7wyu;Cd ShhTd*>pbG<-yqOXYyKAsd|6Wf literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/dao/__pycache__/statistics.cpython-310.pyc b/sqlalchemy_fastapi_demo/dao/__pycache__/statistics.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..16396bf2451ff1459346c73e25962d951741ddea GIT binary patch literal 4637 zcmaJ^-ESOM6`y n-AA*qSB$kw4_jI9TPPT0xFpZ(^M>uR^z?1&aP*7 zHg{&zI2ua@2f;%T1y$mKNbFW>MV|TqQY8@d|Cm>rwthnhp<*>LzjJ53AFj!+?wNb< zId|sF`JJx`$HyHFzx1DX>nle!?H{xl{^hZ_fDye1A~eAQt-(sH!AqRcng@ErC>d(5 z2WG=6S!!+sxrSY`8~IXRt T9*82w#s@FK^d9ra?hIPLZ(>lHuHhatGSEK8J7gVnKjm>h^ zi(;=;gDQ=1Re0elmT@hLYn5oBwV4*8%wMB2RLtRF(OHmVrp=1Xp0xi3I&S|Pbj (sAC}K>B{2fF9)2=Ti9O3LNr)C_+KuCwepS=CS4!x1`Ckkahi2QPDG`zr90{7ni z6M*(hl> znCUw30@603+s?9icAQy^-=8)3=LTG0ju}i+%v4D4{U4 0uW{DL()#i=xPAq z3;@vUraTuLztE~kL_)u9)6UD 3pX3Oq^i zC7&X48YH#J3z}X7iQd2IHQ*4gnc?^>u`TIG?I4DC#BKRiIz<^lK0`#|*;8C;@-%j% z2@nI&%`u0aWc&?4_&m0D7C|axrTrg8`#~J_!^%e=$6@?{4B@wB##Ul(!_pf-IKdup z1csd)u*)#C>P}*f;HU$K|A!-)n0#L0xK23c`#2(g680N@9RZt}fnHdC1q28>Rj(G5 z6)r;nI*Swtm9WuT`Uc&VT;+HlKRPl5UtiQ6dpLfn9{9}+MDjTm+o_}Q3nfC=%_#_b zI>ohyAITR;@asfKk&;Qzj)oxp7O@nhPUc)Bpgfw21tB`a3dp)WOuvoI)DV7D83|4@ z9|h<|jHnJ0YaJHzx{kbPP|ihG)H)`1tT+dNcvtV_v2ws4!%l%RG3C&Gi7uz`MgGh> zgtG|I$*$I LCCr`j#8(Jq%R-yZ{Z51y$P9!IPw076NBzrqbhcG$X|` zI~w(nx}9EO8e~EFC5WW9GBBmW3$)a|sG{P^&9Yx=D!zP)Zbz9g^92<&nQ{9XM(4p+ z;WCY4N5 zW;uGtBZ-)L=-C0%f2; zp$$`oirO)bLIqhWQ!q3cme0~`Qjp 7Di6! zcg#UF$x~3yHB*BUN@h*F9 X92;Qhl3J_t#YQ-cW|R<4#Yam zn9;i;fvG-P?~GArp$Zr}W=ekp(~syvUQW8KU_@U7QHkv6s a&!k|KLY}F6L_o66D38X-V=eUb)1C0mn;fDtbj4*$d|~B2vnRJhunBCa5?hg zU_AlOBz2#V%C5Y>HakUuu!hG?(R1*GX$oy&3hOq)x92^%Wrb*JQ(7X3 %wbNzGc+3}aOWvXq}C6=lFf(@MUt<{Iu4Jqbcth3}!s-Lv_GO8G^- zh)&7I-$CnJ(D`Q*dASNvS6^OUM#O!S=1gTc_gLx-zOB?-W-a@ZgWZuYu7yU3Z@`6K zEsL@*#M2KKUZLJp70UFfhf5AZFte+QzB3O$Qz_H8ilhjUmqAj!){NCRoa*#duPCXx zP-Rf1Sruc-Btw4D&n>CFh?i^!{t{Ju_4!!T3NUSv%&T+8nSCF0k8}Qj>&|_9)-E`< L A4BJVF( literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/dao/__pycache__/students_dao.cpython-310.pyc b/sqlalchemy_fastapi_demo/dao/__pycache__/students_dao.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cf1b1574775654b6f7dccc48d5b28aae16884898 GIT binary patch literal 3938 zcmai0-ESP#6`y ESV%!ZiPcCg+OU3yJ<=SC>SBNp%C#;^zFVjyY{}22h^9eK+n0eyY_CDFspm^ zoIB^9x%Yhh?x|$6DGi=a{&i)3epu7~jl#}H2jMXoK^X|s81Xcp6bM0{deqkoy5e=u z@Xdm$c*C>&L?NMg)3g0#A*p!FOZn+S+Rqd+N=|rLKUc{4LxmxtJ*hF9CC_Rsd4?8- zS?Z{kPq*NkTAs+nQ62 jo8})`V5Y z%VD0%?9rG#BzQ68UGeD!1|qz-pHjw(o-}^x24M-my7S3_@EDBX6ChkG5T+F<*BRjk zquiV`n9hu|#u-wu+OwvbwOB&UCfc($w?Q|_Qff8{v-c?*S#Gi%tgzS+8$N4-om6|p zh_W-v?olh!Tu+XvUpkp#_p7xdJj2ZijqQT}Ed0~9+_9NqyV<(|gf&J}ad)4d+8-p0^lc~1%4nO{sq-<8&C3LvsvJwS%bROgl7>8hdIte7wYFbF@ zq((zBuSeu01>UG@V3Sn84GPU#z4i8sn=f74{P0Ti)s4paHyhVpZT$J_tsAd3&V97M z 2@7t9=4DxD|_|A?r}^HPX%c%o8ni$9zR7QLcZI>G%VXRa88#Rb=4+^@{A zVr3?Xb0}~?m|9qpV{SQE03%Mv9Zt2p2o R`lf&uxdwo9q (q|8khdkxc27eg*R^9c(M7{RY*S&8!ugNT-dnz!D@5$N{fJ^dmd=@ zXTWW3bQG??zjf)I#(Hh@0%Y-8 ?AD(Niezf)R9~x`5)*ml#{{A1$)#q>B_#If@ z+PL0$VXgW6rN-s;x2Q}*x`oxiDODJk7UN;j^{N<~*gEW{asB zN()jHa!G|)rd-HW?(vW_ffz1RK3Mh~R`nO8USv#KrHb#np-c!qCwOo|CcCgIZBg;O z*<$Hr-iXU;98H+~6u=|wZq|Va$4R5oM`cc~q~O(Q7YbrPa6gc}x a`%y%`JvsHiDDxf;2rBHeABvbROg}wNzRi1g1BwFo6(uA_O8c zLf%pkM5}nB#@cUN^}j=aw>B;{Ubxyib2SdU`f@(e=U{=Sf#jZ>3wS8LiGp7Ayu2Q} zC=U~Aw%;+s&+xG0mB4`&-vP}4QR1M!yl2Pp`}M?qpwm-DxCjec9rtU%+<9C;TR1Kp zo7T+sQE}hR+CQ7?@5aa5ym1lJdHv<)>-G5X@qw*D2UeTtfeqYM{~1Si?A@7Nf;9Xd zXa(3?jOq~SFANyVdj}sjUN9|fNFAqK^mz%By7MG}!J*E48kjrJTqi455|DstRU*bC zOWirK7vN1q)qK7^Z`J@$BKjw|D_;ksz_pRCG#+VdBqD`HFmC~x7?3o{$W(e(Ev0;_ zPb-hzCST8|zualxh0RLCb5C-0Es1Y|9A^mLe~@45#!~J?)mW*UMv^S{dwG|-10BEW zg)SgPnYq{m{Rq|uV?cH%DY5A=RM;epVKPi@vb=wX&j&7-IuvtHQK7fHSbYwJUXNpT zVV0@lQdzd5M|v=^6Q=>a6U=1RI$1Fyqh{B&!`iP?GjzpVvBG4eM`mQ5fzEO9f#nQX z2d^qLPWK^oX6cD8QfIqJort~Px&Q$2p98SJIIWv6zXvIP^MmymCYx&)5i%9<3Phu0 z*go=8B@g;SxYMAB^SS=usbFBesEk+0DfWRVO*iCzAQP~v7=}XNX9ZTEcmN4r9X$bk z7-tcXWV)*QOz0cJA~q}BW72%K=s`QvclYMnnotJVxlY6C01b~q9ODWyDBvhWI0x8y z7aZ-i(}N&7*z3l29)z!qE!0YHY#9KlW2m^n&8y;OBeW9jxW+7X!zPy=?#4~UR^71e zxQR#Lv*HIxFf3vM$gw-?Xiz8ydA$w4N*x`3hgaiku!F$A0hM4skY2A^^sXN5wE+zj zq@E_e0VHouPsjNfi=)zZ6o@&FOgRqRx>b(@pK+YUYSBY@LkX{Yx8!r^Kbb&Sm%3XH z1(vb67YP=jcnAqz7XlkVkpv?30MhUKC}JGNPmw%|WILM_hnKQQ1IfV%4g;|@O2-H_ z+GBJw=1r=@O{{*#ZTSBJeDS%Z)6Xn}{*RjUztqayrn|-o9T_Le;&gsQ=C+&VsfzI9 zGbGw=bKG(~xUJIDPfw{ zdl`4!6T@(BdqBJ!axvm9Wf&!@WD u%HilzX@yG*ZuuGIZh=>rI`km_O8X~qfFH$t2(Zo07})CI4*-~q>i-8B3KNC^ literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/dao/__pycache__/students_dao.cpython-312.pyc b/sqlalchemy_fastapi_demo/dao/__pycache__/students_dao.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae9aaef780ad85e86059d893f812ee103ac9f1fa GIT binary patch literal 5460 zcmdTITWk~AbsnDa*dAx>gb-XpNPv(`cAFHcg;k(kDBFcrn}8G$t&8v)&jcpeNthWI zg3K1W+sZD`fW$6AWt-5lT_e~MAys76YQL(gQhzcslG70tsk+IMKSPA}x98rOv17|& z`6wT~iSIr4o^$T&Jn#I&@Anc=Hb|cgZ1xkxe^AFME*n@p1i)27A|x_SB*-vHBAAL( z2|7$;n2x&=Oqjv2E6yg|VRwQHbGXmMJqd5voA8BwBta3o35k85kleQ^YxXcd!ik;* z)DcP3-6w0BGBgOFf6xB?`@VlFCJ*b@fV)pmO7fsCQl{Sqcd2qzmy6v4!xD4>&+Wxb z(YWb)Tha8GwUkxY*qy~$0Im`;5hf)fOv$uF$}WkLnSPf K#R;ejrVSQl LC}0eXD* C#J{_C8 zp1nnxK24A6Ni7l^l4O&WWId|HZxJGIGAEL t zSAP@^F|2%ZSRERWV|tf%A|8#$j>(CUh>e0hCWgAC=uj8z9Qg~_b#$n6c*LxUVRsR+ z$4`g)ECR5M&T n^p5q9C$1$7{uSuw z`9_0poM1l@ZU_e7g-4nUzG 0d6~_|yFO$B*y+ZtfS^h4-?S)?;fB-72y^tk&uZ1R+xb z|JUEI$-258b?9h3F4C5Iu0tefR6|z6w0s7Ocm*`C;60vAMfa)w! zV2MEO=&8)9>+YP;oEO>*q3w=4-`;JscTYu)_BV3Ej=Zqj5O)9Fl@ogMLZ2b@P4EA4 zP6+3P!-jA;C%iMwy`#3kY%1~+WiA^TD;DV;0A9XGm$>yRjyPqxSvx>f6RhLXu;`j# z%kvYT&0qYZC9W_3^5NX*{ke-D%zt#l5~d|UwweI(Rj5e%B4r5<-HnFUc0?9jB9+LI z5pZLt8>`FA!frql?11V8g!WKaIr?tq-HDYT%|)6Fh>yh1TlKda3N-22gk{yMu7s&f zE*6h!8mt{#8VB8g!eaXy*vQKln`2F9Scq=qxpgV_Yhw2D!nJMs44b0PZT{MMs>I@I z(O05U)Nde{{HPccOFK@{FR))Hn}ch0N{YrYzqDVrTBJ_7oRzA^XvV?9dD-X1Xi#X{ zioPb ?uSA{o~ei0Xrqf>Pzv%}aE>Dg|0!yAKuUdoAG?M)zd)TsfHI*W~#P2EXCv!F=mh zqjl@lCZlzGj{i=YoZ&Xk`hwHGH8X*r6%EImt~F)17@ >$6^F3upiQ z`18w_%Fd@R&HZW|zE{u*?Wjp9lIVF6^)2bEow;It#j0ACxz<>(wW^w0j@k#i(@sJK z@15srYM>z>SZ4&*O+<|VN`Gog=}$FHoo!r`W*=~&>MGap%H$S9=$_`fvEo5GhrH#2 z1eM72_SzS@4Rr%17s0R4NW}C;BJko$|x{NaRE^8b|L_)I$$kC61Fk9NrYRc@@1>aD|+-wh@H+J~7J# z3zVN(IkvSxK$Goxikd~5U~BPsp$VWT6vafzv4aHywb@-(JGJX6?%Tu&Rp2lm&1@Pw zS|FgwYEMyPlK=#7Mwpo;TE&@-9q4~m2#orPzm92`2|)S@?d*!ivA)Ya1qNWCY*;&{ zT}~9-sK+@y59)b|x|IbVf_P#@!&5Yey$~AfaE{;{Z9P8WWYrTEC=as@5kixNb3ucr zdV blCa6@Bg4wzQ7nBG#Vkv-<>EHE?UsUlSKSRH$aFQ7h(U@^lFz&Zx&B{7%N)`D Vh}idtX!(lmA<1n|2~^|r{ue*tO1l66 literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/dao/__pycache__/teachers_dao.cpython-310.pyc b/sqlalchemy_fastapi_demo/dao/__pycache__/teachers_dao.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1e9f9e3ca4288a4210a4975dd96a5c1a14ac7ccf GIT binary patch literal 3176 zcmbVO-ESP#6`wm_yI!vy#{>r`YPXaIR+TK^rNSx*lqd+PN+Ttx($>{zviB~YWM kz#lNL^~|oH^3D_I+?m;32e%K*>fXKg z+;hKv=bYcUm4Shb1mE`~YbTeplJsBf^nMC-UV`EthKfp**pfpEgkW2?Wk)F}j#^Mf zU$HeuFX*DJ+9@YpNE7K5iE30oD^dN7T DMO>u!OGD=+DDG9Lm{cHCD#%QsgsD_!T1lk} zRnMwtNI{RK8cTsxrzs$I`Tr_R)-x_U+K^r&%G*bfvI%e@UkUbWn_BVPr(?xtFEr zFs!B1hv>eu8tgkjABOAi?_BoK%YX7^dcx0o(d7-euUVAg_{oRxYfuhCai4?A0~1(M zjWkG8S|N*MMy^Q>xh6NkB+yctlK59+i46P6M?RDC8pmb)j8mb^HfYtE^c54Z){7O# zu{=M;S&1`uBCl}7k@pF0dcug0#?ehg^}}Bdj*Y+OGVYH5*(%e@-`w$|)5QssJ4bot zBrAH@_a-XkxcmEYcgi+xFs?IgluXw%CoO|Ar!r2>%6PoI3s H 2TPZuUa D5#)Vlj_c;i|ye=fNAdHbW!+uyDS^~Uy $vWpd zd*(G?o2oKC9hplnS+>VGABJ=JTFK(BmzN_0p{Q#VK7<-0R@t2d3nTy<7B#BnDI9YV zh{v?kzwW_rcWpmi#1MnIKLN7iiBG^{KLrv1RVe~0H#7mLT)hN}oy$dlww7+THdYfr zqh10;3}~=&835fC$8hl-z^)g^WbS;h@YU9x1pqp{@P!2q#cbv=`ogoj0?i4WEU)v2 z;E(HA?Zaw6RDPyAn?DSK1acgF5b}KqhzV#2_y{Npz@N}g|7sV&dv$k!jN#t#)@PvO zNexniaBs>G=rSLu$tPumnD3zw+LY8}0|`KcJypPm)#^Ez)`2{7wa9Bb!ZFUgDld=a zj`J$ZwVP|Lm5o@jelhsRhv2%0P1{X|k_bR>Z@wQ~TZ8f7_P={=5Y{iZnqNd~bhg<> zhz}pnt2_k_j-c>Iuo{3W;Thq^dr;aTn8=s2k^KzYdVRus928tgPf}JN1QyVN4S);w z_dwgLT|^j@5BKi)?H{275CU*iULZ4y2Q(1FtJV~R@sRY_%(y(G&FG$5Q)^mHKcf(7 zY6w6EpBCJz*Hpo_D!{E&fp@!bhadbWy!<7wLRi1Ob*~xDtpiB}OaF}ITbqsG+$Z3U z+t+WjKHCUxz8Bv5`u=7&`o|_sZaO)7Vk{S4`Vz<|*m!qq^J;tjdI!{4C1E>E7-PAZ zTt1zP_K6mTeR4;qsaf`{VlG^31~)ErS4lh|o^WvywUN|w-EjK!@4#E}T@up=^(*ar z%fSaXaz`p<)>-d3Waa_(X3?%v1_9tQFQ4N50Cv~(zGivMas3nwnx4mn7w|#Q0acN5 zge!==(_a;tU!+5h&fzPk*tD;`VcNir4>*b*Dd$1W#pSYnSu#WhlZ3Ii$4Meh5&GK{ zmsQIW#m3V z{XL+Sj#@;vsfcVb7$dSpGVt|EsRS;;e~TT(wC#i$o&!Di@p%{%EPJ5u z^l*=r Pg_7NiQ z`6Us0NAekeu=`vZt#C)2!hfnO-0_AQb@5%rMq@s3qvPVK3J3nz6!8S?&Om$kPyT=9 hqJd9>C{GG9-{qoy`VSGRFCyyV-IkSyNEUv>@{bUz2bBN- literal 0 HcmV?d00001 diff --git a/sqlalchemy_fastapi_demo/dao/__pycache__/teachers_dao.cpython-312.pyc b/sqlalchemy_fastapi_demo/dao/__pycache__/teachers_dao.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..917e5155ca86179ec18259641a0ad60a67e22813 GIT binary patch literal 4139 zcmdT{Yfu~46~3!|NQlSA$Pim;$hK)}3lA_;JIO@jal@E8ji<4j#Qwvy)yUe#7S;pr zt{TJ0GtiPowAg5-PKXmsVCooB>_F3YEK_FO|NUc)+{)car }CbO$^exD%i>_v@0P zM3aetOY@$P!jUtQ+%1Y)qt!k+Acj>5+gSt9tUDYF!<SwnZKsW7LuvVfFShydyuva1ax`*{uE4W@q z0oSpQP=J;3fi-VDDN3=Bn2HZ*bQn s%mao>XRkqOn{cLGs^YET09l9E QyF9 zWkn6ROvk`O3jSh2kbPL) z8ciqz0I`i&C@O|hiE~3=tpKjJ$zyn_Z-N*`B` %1-ytOBSX$Us_e+6xA;^x}&oDG`U`)@##cfmEt zm?Y%gSbPNwKL{HwJWz$!P8$mQ>Iha()xfIKfPlUosk#FHwIUzL^MM _AWW0ajci;EzvS=^ce$Vq{nF4tqc|4KI0ObU;zr&KibFNxECsH?@;B p?$&@BTh;$_4fUr#jr1X3}h$Td>Yaq4AvzW?&qdwiTNjNl0wmri5;q zSttip1{jo1Q83`ZW4!-c _0Fs@vIv~1PyEUpUtO8e-~4dxz0r-U(`z3s z>o+HjkAGK5p22~z9F7a(si0uIy#!pWFaKh7<-PUAtIiIVi5+HeHW3u`@i+DC!us_Q zb02eI*hl!@pcqc5(THHo&+5}ZFRx