From 76f2b67d38ad3ab6634f0a843d029d40f9889301 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Fri, 14 Dec 2018 20:35:36 +0400 Subject: [PATCH] :memo: Add tutorial for body nested models --- .../tutorial/body-nested-models/image01.png | Bin 0 -> 40992 bytes docs/tutorial/body-nested-models.md | 213 ++++++++++++++++++ .../src/body-nested-models/tutorial001.py | 18 ++ .../src/body-nested-models/tutorial002.py | 20 ++ .../src/body-nested-models/tutorial003.py | 20 ++ .../src/body-nested-models/tutorial004.py | 26 +++ .../src/body-nested-models/tutorial005.py | 27 +++ .../src/body-nested-models/tutorial006.py | 27 +++ .../src/body-nested-models/tutorial007.py | 33 +++ .../src/body-nested-models/tutorial008.py | 17 ++ mkdocs.yml | 1 + 11 files changed, 402 insertions(+) create mode 100644 docs/img/tutorial/body-nested-models/image01.png create mode 100644 docs/tutorial/body-nested-models.md create mode 100644 docs/tutorial/src/body-nested-models/tutorial001.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial002.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial003.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial004.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial005.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial006.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial007.py create mode 100644 docs/tutorial/src/body-nested-models/tutorial008.py diff --git a/docs/img/tutorial/body-nested-models/image01.png b/docs/img/tutorial/body-nested-models/image01.png new file mode 100644 index 0000000000000000000000000000000000000000..f3644ce792ea70e1e1f701c99291aaef7e83172a GIT binary patch literal 40992 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%0DU|a%c zZ1)qnq=`)}vfsZ6kyP~*M@1RTmJ~E7Z|r*Ud^!AWx>D(z&oiT>u5x2ZC2%HyL%w=gD3M~SSQ%vl(zZ?G5uj%qsC58~>UeL6#1>R<%8jeu+O$B+n%Eo~ zKjnaSl~1yaiUsSsKb7x2yU6{_kJB2_X=#wQ#L6)kpzZzK!}YjutbLFKZ82}dsZw5H z z$gH=%YETD|9=pHj^MeqNa~)bq_tD@^o%|a2`c3}dXJ6|E_kNT;yx*j7%lYIkGoQ}f zM@t^!p08!nU5fUzh_GU_+k$$2LAAYy&^OON zb)(_Oa?qjQE>*e8Ip2u~xIIJIy)qa9pp471;bM`x{$rtXa`Zk#x%izHe9L%*Omu|mOAvc}!I!~9^UiG#H_DAo!aI)^y0?rbuGMWol)S_3*l+fr}2!XbGdXa_G z?5*9>g59JG8?H(H-qQ^j;HqhNFPk?pb}sw74z;GwzS842=|FgqW4zj8dfLLef&!ZX zFnFfzl$o9LEiXPtl`@fHevB#>R@5Cm2)d(YU{~*$qCggvUu~|gy^{*(WH1gEA}@*U z`{YC;p-vek{)vUYf8!01PCwkgtf)b$STJ1?Lg=x#edrAf3-tLi*F~m{DIw8z? zbi-NLYt}4kC)SeWRmtS5NQ6|Lej4&+g1&CXi+zb_8_wH=5Bj+M&4^!guez$Ls;0)- z(UI5liYdAu^~H;wot@X;K4rC#ur44($J0@|dAdVNOu6ZA^h*jf_OR=R2W5*CXKGUJ zMHXhMJH{AjKt-P8aq8KJCtG!s3n-6XYe+=g#TihTX$yE(2Sv#jY3#4LWoItJs^s81 zzo1x6jI;zREEx@yKuIUM{ktnd2GGCa#h}g~vRZ#HA*d1G4ljsVcnEx^p|7=e`6s#l^dg9JEGQld@UH)TL+f%AIofc*DTs$w1u z4yz@MZ;*=bFc%2gkk2>BU-_stA7rKP=H56&Wg!)gE;%BX!X-FCrY!U0u?%xfs}Y4d zSjJ`!`!TShhnTlBZL%ArAMx7HkP;?~VSoe}@BVzDN?uDfF9UfkV-~=7rK@sGTvJ18 zvO#l%Iy{#a>vrp4ZssCCb|+wDr3Cv4i94C)#rG`w#g;YI#(&#txNnPnb3B?(&tUUX z-+7m+Ie+p&-Z9FyH+P=gyb>nj@$3?{bFuUwsP!>NE)N8dF0KWDkoadyv6~$<)@}Ia zl9F5Q>bV#Tom(cS3<1EDp=t3VHihz1VgVN4VA}2Y_ua29(|6nZi#*%3+jgSUIVrSB zKZzxNXK~vkWzWUmwSrR`>BSj6rRydN$ks~x^EA#8kJK-FrDk6jwcgzRiYf5OZ^3u_ zGgBIoAMDsOiPU?rl2x0bx3Kl1v1gkyDR+i7ZyHzL0q-S?ipun_ur}1+36B#;?4>+j zTP@>=*N`_4CXZ5=>a0utA9Os}&E0!;o3h}#XCwD=!<<3jnQdu-&(k5^)T+3EV4>Gn zfr<)e@#U(q>dg0U#cBonFp=rWXj z3d^VaS47y+ZGe|fcA}oeNoi@dtvvm8DC6%qmgW#AhfActxvGha2C4~k|R0bD< z1vOf3xq>DGQA#d?C@xWmLnCLS2AKbBT0Or42|&gv@q&crYL@KlAMYRBGUQM;9NnO4 z4(?zVv<7sgEW4gfbh0<{UsIcHFxRJ8eD5vx=pgAm!}kc#P_WaLbrzKn{SgP<>aE|w z`h;O{A&o?Gw5pid?DnDhiO27a>_B1^3Sdh-d;}1pdZCXYLX6R7>W9nzxB2MkE^xoL z&%f}b&>CnxarrZ~UdUiPEjUTg#Ak~Wz|MH?#c?hx%%*qV)C z{BFN9K01QezrWg6{o}mcQUN|#-6iE(M8NJ_bfFIEn{ZvgKsF6fJz%pVrZ z<^vrKYd**Nk-N-VxAF0Cc%b7zy2R@-j7a`e9D$Y0D=6hqOz(wgWtai40ayEJ}sMmZX`_DLeJ zzFaQL6YnCELO+>lI#N$*b8-IV=CJW}72xmN0m2 zmU#3+dV|Qs8xuoQT@cO%P0#_LSR^R(((Td1?2xom!NI{L8!ELjHu-s4Ypn%?q&{9Q~Ciw zw*|9`VS2bXK>WlqK!54Ctva{s75fJ!uB}w>1Q8Q^1Zz0>COvyXN=^n6mbP%QC;}nf z1e|L*sYa#ff_CD;?O#$BpY9Fu+DhU^xf~$R5ysTxhA@^QsF(E$$0K>nioKgA zsS(fjutEM}P>CIy_+^BlpG=ObiguGHL>s>Px`SRx-!P1c{0G`k?49=E4PnOjOD*Ke z#MSObi#1cn>EnI)Bm3qsfZV~Y_h}XAt&1_4LdwsZlY7c!)pt9baUm2fKIgqi&l=g;o1E{nNw9c}~F-eL2^8>rvwoM#9C+Z`*bo(C-eOgkR^>K-VH zOx{j;McIO59fyy2uvSxa61EO}n@I#Jh4 zk)ZpFVcycQ4;LF2qdu%FXULJL(cOWs(T%WTPUU+fye8OGc> z_THN4-Tb_B64kaC{6<`euSIb=T);`8HTtF`bm`hzwR5E+YVx8|s+q7sc|rAX>d|av zK-xl~SSZWVjMKRy2Osb?2h9f$;j~zF8vBaQ*V$OLXUrhExn$gy_MfyK%PGeYq|w_+ z&i}w#zB~wbF_z~<4Kpwvn{*quU|FrF7!Hd{|U$8pWN)j->=-8HJWPc2E5cCJwDl~ATn~1Q+vQ@ zD>q&y^jYCnwt}wx!q`54R!eQLdxhdi6I568%azRQJN)d&&!J7=q2sl;Bxma^4)*S2 zGeuamDry=U%ci69&-t*@<*tW|^#o{ng@uwdu_`Jm7iVX@96SuRu25Rd9@tEs9P8xcE@au5 zzlb+R7Frw(!=aH$(KT9LyCV|%6DA0wdlR7?N_=7A2q>pfzlMHGjUzLd^aR~;=@*xL z*pw}3mu-2N=#8InsyPKQAC2%LXHd>kX|?;@9@M%dFVD=>_&h%J9qmuFCc0b3<;#S#r8huk!k#nNm8^Vv1 za#>xhe{fIMs~yR}* zXC7$O=3}p;z0$=`+!{Toi@1*K$G@*}UbpdFhAnn|PmfP2-N3ZV1pwl(=Ujkw@1s*2 zE8RK{6_=wi+D{u!tGzacAG8l*S>5`C3FjapU!1rYjGe8KtqQ?BjQC9>8+zrRH8MvXQ3`7xwbZ!H z-24LZ_bA`?n9L?}yv2yeB;Fi02@sXnOpcDF#mgm}xemak#TkQXyRs4AbUzS;V{!=} zrGeIvvTW`PVxypjH_Z=wU~)Dm8mrGmnTq`2R|6W~+*iMC8vsyJDi z<3cj@l3q*p&8}kCJ0#1&IH0D~?|k*d(`irvK&o^*Ch#*Of09goSGOi;Q|WA}dWfxa zH0Tv~xP(eMDQn|u&&b>7VQ8J=?j+df{9M^eq=Q=vHatm5N%A)@MC1eVz>Ura5&}S3 zO$~Nvx2z@owAD?oCNuca#tumt+`zH9SF7K`VFZ3pusX5nrpcUFDg3T!Patg*H2k!MKEj1~9mt0Kj z8=UwkWhrz?Y3(6gV`x&#oz;D2NE0~RrOw^H+=-uZ;chp-)pEDY$06j=Ry*!h&d$op z$~eA-%~E&cA!&3rZD_4=E?GDEi&M-)iy6x6M4AMg#5ioJ7@N-$pZn#ng09i`KOkp< zkVz9WE%g+%6nb>Lbbm6*jDhK?%Xy7t%(W~(N*L?Z!y*#X9?ATUNopj)>zxq(+gJIi z(9t79aTuS6Je;bg5>B&(l@K)9&uVj6F71|Ip`dT)Yf9tce_eo8v;ja$?ER zpr#(7k1AihhX;VBGFulbvyq6Gi5k=c!_>;C1aDinKbLTVNNYc4D$(w}thgMw^3#I_ z0DsA-^f%wg%!@VDRW;X3niP8h*f{G~l+K%P)z2#HgVl z;ciPAJzNk8_eTTZBS&+TJdC_>FkhC3ykx!a$2$5=7azkXLJd+WQTze#+y4G$BY}h7 zY;T6?o0gt<=4P1FtBa2Y%#$j9w<}y&O0I14g{V zRY==eqlY z$!j$zQYZpS;z8HhN=!S4GUl|-I8*tr001`rL7R;Vi-vnvgh>wTo>lO9zERTU61U^K zs)~?RKCVP+GY_n6@Si^sE%4EuE8nF&6$SsA_p$)b^VUdtEoLLkIyE(`?cnMb8{8N$ zO=bhBEBjWgY(hLgQV>HEvbWVu3izIBzTNBHO;fy-%=agb!#wC-JAz#`fSbE#J?p)| z+-rUt_@dpK7j1Nyk&~N?eg5FMST{u>gLDZN0UlslT3rpOzjuh~7SU(np&tD=*I&H-#5sdWWj1sTq=q=)JM|1P$}^=6H82`Hs@%R>C{G%A=24@$G>v z!aC=JIFE9Wt@xc!g62BzpTYi4{nQ$0g0ZEMBXu4ig#UAH)4hvA^nPC-h2k2Ey*{L$m0S4)l1IyBi>RL6GCKoHN$%*@P|7Vj{LM_U_@5h95@kw_Bm9pV(sv@YZO$BRS$qMg&_wJXB+FeEY` zzE8br6Qv)ARq5o4l{r3%B8r(dBOa>^)xp+4u@ak=m?hOlU!vH{T_{*s*FfPToQmVh z&XdTKb5Wy5?bgWRRYS?i7R-$Cg|~oBII?{}Rw%fVLqPCsWqAC2NPNxb8Qr(#;s9w) zE5ox00a?*7NjDiN1@@4UQRJ_8%$yJ<1m>6a`S zQP%9qzRZlsGKA0=48|_YjNLF8_p9Hz|8pPw&$;*9XZPICgLyLV^ZuN9f8NXM^R-uo($U2^;+1!&#_D~&n%3L3g~EQ}aJQ>eu3ft?mUNDr`o{k`-p>49F9?fW5sd+Je`8uV#f`5DN zb2wx+4@BKrYk)VCjT7& zsmj3u!=oh&j1}<2p`lGkr1iaf_kePqL$~iPe_@{T9wxz_1Sn*6<${@}&Nay>K1+U( z^OntTl@B!wPDA|?ug94VPP_Y_cl!Y=-K?uxN3=F(tWTR54W!AN1AVWna|GvxxW?FnXTlJTLzm{uo^tWmDrCpB; z92OiF%avSN*dtab#adlDxAjIXA*~+>V0(N&-@zBZMPqsSS^;I)EjhWRZ7M2+qPjcz z>RpJ&DVN(m_E66Xzz_I7?nKcG)yGJzLvnF-(TneVAB{4F_T7r4&zQNSO}|~RjaHSHm+w-^w$cZ|k|j++=fKzebf8Lm zd!o1_3)izzx(O_15;$hg>C5?^{dW$ z*|1LYi?8`!-PlDlA=r%_e=XfVhhU_mn;Bu!Fs`;DEiElgO$n!Vzk2zyp`qc2ldq%W z+#!W{wARWdq~P6*#~*Jf9Imi`w=a{+EH{g83cU2Kw^Q5(6oCr0ccULTH;m8mK` zZS6C&B8Mz&`ckKQ$?vg|2Q2vYQ}xhb^9&UF4yH;ghyQ%*>G#Jb`sI)58P81xku#fDKYmt{7bh!ly+cpE5*XN<%-x!5LS5cJq)sT|t zzA;YojI_62f`=Z5Q;F6H_CA%y%yJ$&y7Ne_j}!{_YSzUXRLSv)<0Nu-o$79N#|5j$ zKGbZ}EIhk6=M)0~%A3I!;mtjwCJ`NCS49kynTsp(0|)a@a@_{nSlXp^{NSMPN%yA? z)u~Ml=-GUM<~j-95QBt5U~>gMKEIODh? zrDYfWNSEXJX{U+-;RqKOmt5}VzhuLLf0n{J&xZfmw9Cr{_V(E!8+4!J23$_wVNi?9 z9*L#BQwqYHAoi8L23ReNw&p-$%frQSxfrQ0t5uQTq4z=pFjd&L0*DXE*>SL74@KGM z%}88@ljRGnK%uNB=$h}hLo6)tnz1~4dwbWpW75;pfqMC-S?Sc1F7Guli%kNsl!Umr z>i&vsSJT z+VKX_D?)HlP8|pYVrFJ`|9G<~8+* z)dTs!Ug-KSSIWESiy_QCB>JRM+P*I~ooyVHpEXsEFs-~J3N`zzb=ypGG~O(4nYNf{ho&q2Y&K9QYFBbT?kst_k%Sk6 zp5*yFvl>4|I?~VDZlqZ6SplQHf*&3d9Gszo4wwj9__+g=$Ii~qOh+QKFq%ePe*T=U z)Lc1prkou-&)Y1_f0siB@)KP-2* zQ0N?lFv-}rw)T629&;33VX!2iq^DqC=HC0`Jv>;=-@0IR<98~4BE&H0$;cf3S*LCc zmh&5S1c@WsT}r*+1Cfl=)r*hqoOol54z_<9Cs|8){F2(CgR}GBeFZO+2~oy5`H3gR)yZQXcxoK2|ZJ*HK%_xUH~ZIk6$-Mx-F%v3!*v8e&i zB1Br-@~O^Sv&210RN1j~bj-6WFW_!=VLDx}SHRrY-MvgE^MG$a&|@y{O5q14;=V8X z)2Z`IOQQsW@-5MQDm7u>^}__kO4HxEJg2f4JvMwJ!dYV%Tu#mKz~SPZ34HM(wfM~U z7w#N2Bn%o1t!wroS$aO85@ZV!1r=3(b`#bX%Qh-m`w2G2M3GQu$o@IqQ5LHBD?8%T z+FzzPzM`TZG6=9_g!gaXnt9%3Hv^~2ds$h zvmi+_PW}<4fy+bLu1O=N*6AN?CH;&z?1&x#Dfu`ST4N3U5)xGc`2^bw#pLGYL+0Bo z_|A9pNFJcU(E7!?d-q=O`sLHr1uK1cP`G7X=@cIs*|9O#tqvv+Ec(53Osl%ByX@iV z$$I*m1$J9@K2d@cmKQ)8gxg-Z9YcXd zL1_kA0+x9>9l|zw_`f$+V3A)4q!!Nrrl~IkgudiCFcU&jPEl3t)?Lw5Mfew8ao(2f zfoqN_R;|r{$soV|dKy4mdh2@2_0e;=9BWOH>tJ0J?S{zyp8CqnQLp_^2nZ`Am!`b z@v#^d7MA4Xs*x zjV*w$Ssd7zjagc#|LG3#k~$qO(Az8+Ey}^k&zg*v+}6xq)h>tOm1rW0H8)eK{7bX zwh^YReQ%PX4I=z~sx?w=Z#GFMNzC8hf6-3~*&{bqgtu|#;5adQ9p~sQX*v_8Rmx{MdGoy0cU{}h zRl7fvr>S#S8_pd)oqyboj;S0!Of8GjkkKcws9Mu`<7R#K65$71aTjE{&$Jbq6l8|& z)PK|To&Ql`dE?QeN4*8=<$T-%#|IPozCdCDSn%!TsgV)I?d@&gA&EEJC3>qfFcc&ul>^5p@A90_kcB9aqb7ZKxz@xwQ84kIoK=mzS4? zg+-z165x7f#=e&D0p1FX?aUE(^71nC>C@{Q8$~508G&=Y8C@fF<-Q~pXyK=cfr*5n z1nL!S^d7Ok6y|Ky%%v8*yY27!idU7(?8!gAhu~s;s?T7rkbBqHb89DBW3h$%SMU+H8f>7FgP*C!w zRJ>+kamIKxt4aU7^Xsj#`B2&THgoGYnWmGW7aM2-PbxAnN$IVo>FYkv+Rb>^V^S6Q z=jo|X&prpUBacea_()L*ZpU!YZmuRgvwkzLLon1~FS{Xs{^(#tXt#*oUKc=FPEPY> zwv8#0whf-+GZGfGwN%WQLNDBaPM)|vlf{}T0SgGgY!AU)WvtdIq*|h2P1q6b@K?a) zpBiPRwZDs5K;TAkNw9fx9%jgB4Dap1s1s>KB~z!=8nb3&41J`wTdrJP653r{4WvBp zAHv~8Q@bN;I_EaZ%F2p^N`XYJu-69IdkUz$yJ)RvQ|N?oZ`TO_L%;Dv%VdoWwu+bsL7%CG}c^wpv9Fv_@dU#4x9%M`$} zR;Q;2Mn|c546XX($Gc1wUPLtjb#HGC8fGaw11RMR?c{kDfCb$x0+>YhfWA?$lIZzp+q%W;9BO2 zNxuH0Dwn@?^8ntb1X~$)&IX{kY}Inf_)E0z=;Lw~GI!H2ED0PPCQv`{*cteb~(t+p!d)dYb+;o;$bBn{;8 z_b0YJXa{>vm3zQ=05h?%C6dXWz~}JraE^8&kimxOx1xRMo9pDlg4s3c?j8u-3?SQ7 zTLFxmOrwQ6$HvC$85$-6t_dXL!gp4HWjiS9g#Otpvb(|}A|f|#xc6nMyvh;Cu*ImT zs5HVzMa9Lw0RaK5F~?M^J>cMjtaI*bWU#+qdU$wrbZK!>5y;Gi!DoZ{EOzY2 z3;fTQuTy%JSL33hu1QG+K%wh@4m4q11u)ds)^>2nO-$^|Q1m@GJWLc)d+<-BbxzXL zmoIF0r+}ExP>1xRS|iznlwtZz(!f;c?7W|6Jc7fS85u#Rzn}gSVJ&?e_s8M@qcSJskIBg XvB#*7_c6V5{JoCm1C289Pydantic's exotic types. + +For example, as in the `Image` model we have a `url` field, we can declare it to be instead of a `str`, a Pydantic's `UrlStr`: + +```Python hl_lines="5 11" +{!./tutorial/src/body-nested-models/tutorial005.py!} +``` + +The string will be checked to be a valid URL, and documented in JSON Schema / OpenAPI as such. + +## Attributes with lists of submodels + +You can also use Pydantic models as subtypes of `list`, `set`, etc: + +```Python hl_lines="21" +{!./tutorial/src/body-nested-models/tutorial006.py!} +``` + +This will expect (convert, validate, document, etc) a JSON body like: + +```JSON hl_lines="11" +{ + "name": "Foo", + "description": "The pretender", + "price": 42.0, + "tax": 3.2, + "tags": [ + "rock", + "metal", + "bar" + ], + "images": [ + { + "url": "http://example.com/baz.jpg", + "name": "The Foo live" + }, + { + "url": "http://example.com/dave.jpg", + "name": "The Baz" + } + ] +} +``` + +!!! info + Notice how the `images` key now has a list of image objects. + +## Deeply nested models + +You can define arbitrarily deeply nested models: + +```Python hl_lines="10 15 21 24 28" +{!./tutorial/src/body-nested-models/tutorial007.py!} +``` + +!!! info + Notice how `Offer` as a list of `Item`s, which in turn have an optional list of `Image`s + +## Bodies of pure lists + +If the top level value of the JSON body you expect is a JSON `array` (a Python `list`), you can declare the type in the parameter of the function, the same as in Pydantic models: + +```Python +images: List[Image] +``` + +as in: + +```Python hl_lines="16" +{!./tutorial/src/body-nested-models/tutorial008.py!} +``` + +## Editor support everywhere + +And you get editor support everywhere. + +Even for items inside of lists: + + + +You couldn't get this kind of editor support if you where working directly with `dict` instead of Pydantic models. + +But you don't have to worry about them either, incoming dicts are converted automatically and your output is converted automatically to JSON too. + +## Recap + +With **FastAPI** you have the maximum flexibility provided by Pydantic models, while keeping your code simple, short and elegant. + +But with all the benefits: + +* Editor support (completion everywhere!) +* Data conversion (a.k.a. parsing / serialization) +* Data validation +* Schema documentation +* Automatic docs diff --git a/docs/tutorial/src/body-nested-models/tutorial001.py b/docs/tutorial/src/body-nested-models/tutorial001.py new file mode 100644 index 0000000000..9e0fa4494e --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial001.py @@ -0,0 +1,18 @@ +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: list = [] + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/body-nested-models/tutorial002.py b/docs/tutorial/src/body-nested-models/tutorial002.py new file mode 100644 index 0000000000..8f769279b1 --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial002.py @@ -0,0 +1,20 @@ +from typing import List + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: List[str] = [] + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/body-nested-models/tutorial003.py b/docs/tutorial/src/body-nested-models/tutorial003.py new file mode 100644 index 0000000000..bb539b1272 --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial003.py @@ -0,0 +1,20 @@ +from typing import Set + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = set() + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/body-nested-models/tutorial004.py b/docs/tutorial/src/body-nested-models/tutorial004.py new file mode 100644 index 0000000000..257928ef39 --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial004.py @@ -0,0 +1,26 @@ +from typing import Set + +from fastapi import FastAPI +from pydantic import BaseModel + +app = FastAPI() + + +class Image(BaseModel): + url: str + name: str + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = [] + image: Image = None + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/body-nested-models/tutorial005.py b/docs/tutorial/src/body-nested-models/tutorial005.py new file mode 100644 index 0000000000..f5f19b3904 --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial005.py @@ -0,0 +1,27 @@ +from typing import Set + +from fastapi import FastAPI +from pydantic import BaseModel +from pydantic.types import UrlStr + +app = FastAPI() + + +class Image(BaseModel): + url: UrlStr + name: str + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = [] + image: Image = None + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/body-nested-models/tutorial006.py b/docs/tutorial/src/body-nested-models/tutorial006.py new file mode 100644 index 0000000000..09d8be768a --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial006.py @@ -0,0 +1,27 @@ +from typing import List, Set + +from fastapi import FastAPI +from pydantic import BaseModel +from pydantic.types import UrlStr + +app = FastAPI() + + +class Image(BaseModel): + url: UrlStr + name: str + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = [] + image: List[Image] = None + + +@app.put("/items/{item_id}") +async def update_item(*, item_id: int, item: Item): + results = {"item_id": item_id, "item": item} + return results diff --git a/docs/tutorial/src/body-nested-models/tutorial007.py b/docs/tutorial/src/body-nested-models/tutorial007.py new file mode 100644 index 0000000000..cda802d3e3 --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial007.py @@ -0,0 +1,33 @@ +from typing import List, Set + +from fastapi import FastAPI +from pydantic import BaseModel +from pydantic.types import UrlStr + +app = FastAPI() + + +class Image(BaseModel): + url: UrlStr + name: str + + +class Item(BaseModel): + name: str + description: str = None + price: float + tax: float = None + tags: Set[str] = [] + image: List[Image] = None + + +class Offer(BaseModel): + name: str + description: str = None + price: float + items: List[Item] + + +@app.post("/offers/") +async def create_offer(*, offer: Offer): + return offer diff --git a/docs/tutorial/src/body-nested-models/tutorial008.py b/docs/tutorial/src/body-nested-models/tutorial008.py new file mode 100644 index 0000000000..34b868563b --- /dev/null +++ b/docs/tutorial/src/body-nested-models/tutorial008.py @@ -0,0 +1,17 @@ +from typing import List + +from fastapi import FastAPI +from pydantic import BaseModel +from pydantic.types import UrlStr + +app = FastAPI() + + +class Image(BaseModel): + url: UrlStr + name: str + + +@app.post("/images/multiple/") +async def create_multiple_images(*, images: List[Image]): + return images diff --git a/mkdocs.yml b/mkdocs.yml index 30f803ef2f..84107b828c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -26,6 +26,7 @@ nav: - Path Parameters - Numeric Validations: 'tutorial/path-params-numeric-validations.md' - Body - Multiple Parameters: 'tutorial/body-multiple-params.md' - Body - Schema: 'tutorial/body-schema.md' + - Body - Nested Models: 'tutorial/body-nested-models.md' - Concurrency and async / await: 'async.md' - Deployment: 'deployment.md' -- 2.47.3