From 29e06517cb42f82e3d25444f58523a4017fbb28e Mon Sep 17 00:00:00 2001 From: bwstudio Date: Thu, 21 May 2026 20:45:41 +0800 Subject: [PATCH] feat(api): add Pydantic schemas --- .claude/settings.local.json | 3 +- api/app/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 145 bytes api/app/__pycache__/config.cpython-311.pyc | Bin 0 -> 470 bytes api/app/__pycache__/database.cpython-311.pyc | Bin 0 -> 1033 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 417 bytes .../__pycache__/category.cpython-311.pyc | Bin 0 -> 1978 bytes .../models/__pycache__/joke.cpython-311.pyc | Bin 0 -> 1900 bytes .../models/__pycache__/user.cpython-311.pyc | Bin 0 -> 1134 bytes api/app/schemas/__init__.py | 29 ++++++++++++ api/app/schemas/auth.py | 11 +++++ api/app/schemas/category.py | 35 ++++++++++++++ api/app/schemas/joke.py | 43 ++++++++++++++++++ 12 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 api/app/__pycache__/__init__.cpython-311.pyc create mode 100644 api/app/__pycache__/config.cpython-311.pyc create mode 100644 api/app/__pycache__/database.cpython-311.pyc create mode 100644 api/app/models/__pycache__/__init__.cpython-311.pyc create mode 100644 api/app/models/__pycache__/category.cpython-311.pyc create mode 100644 api/app/models/__pycache__/joke.cpython-311.pyc create mode 100644 api/app/models/__pycache__/user.cpython-311.pyc create mode 100644 api/app/schemas/__init__.py create mode 100644 api/app/schemas/auth.py create mode 100644 api/app/schemas/category.py create mode 100644 api/app/schemas/joke.py diff --git a/.claude/settings.local.json b/.claude/settings.local.json index d5b88f4..02fae74 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -5,7 +5,8 @@ "Skill(writing-plans)", "Skill(subagent-driven-development)", "Bash(git add *)", - "Bash(git commit *)" + "Bash(git commit *)", + "Bash(python -c \"from app.models import Joke, JokeType, JokeCrowd, AdminUser; print\\('All models imported successfully'\\)\")" ] } } diff --git a/api/app/__pycache__/__init__.cpython-311.pyc b/api/app/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4ca7ab23f398575d04b5e2c7335c70d3f211881 GIT binary patch literal 145 zcmZ3^%ge<81h@Y1Wr66&AOZ#$p^VRLK*n^26oz01O-8?!3`I;p{%4TnFBKQ7n56RJ zlG2pS{Fto#?9`aVf=nPTh>4HS%*!l^kJl@x{Ka9Do1apelWJGQ3e*HLwwNDCd|+l| NWc7l%zQ(D6B`c10lP0>hl4*d0iGU}j`wyurZP0EQpf7z9)s zcz~3U^aP zDF|MA?WrQ|#hXX}gcN!Rdn$;aw@5t%@!*@ZwFx3P^WNiq&6}Cud+!nn9dJdz2A8J= zfY01GU-Fr9vW3bHP@u#HhZG3mx?l^ASP;9qXiJVjc9iyWwX zSbZP)bQLs=VuUJ8JJ9w-j3J-JVi*(m(AYnBK|!an*H9RsdLGgP-?%?bqJ-%)BV;A! zRxFpHBT1QQ8@>@*FIcH;1l$)7SP)pA>liD{=k{#&adsw~e^`3*Xg(S?mzcRy3Jiyp z!X+$6=Xj3kxh^xqlHpf^v>53|E%Z#!ajYvK$bE zEhHBS{hxXTG1!2ou!DeZz-~|8zfK^)B##&TZ}uvziO*n_q=lE0v#iQo%3O0j6?&-( z3sckx4GvQ3457?IT8QHLQ@G|m)377iw7o8h0xbvpfvKNUv-gVS)gY`<%PTH>E39Z# zE#zwPyk4fd9w~T1iI)9gJaZX2c!1(7?mB#lUD=%2o~X~X1yLSp4JI2J-^ZH%M%&Uh z^=-Y;-JOQe>*#bkK@5w$m2Shq)vO>cq~nnuJhu%Sd+4nDe1M|y3rB{ng_)j#@Og8h z!JY)qcYHqN*xzb3gFRogD!#%U%IQe?32sO;2vYYa@8JX;;3rZ1)TSMe)@*j)A4ije z6MR6?76~COm}>S@3+^`isRg&1{d5eI&3 zU1`T5dA+f*Tl*+~nrjZ_4u^6_L%Dh!k80PN>gb_5cBGEgrM9Awkv9A-{4sp>Zw@{M A3jhEB literal 0 HcmV?d00001 diff --git a/api/app/models/__pycache__/__init__.cpython-311.pyc b/api/app/models/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e374638098ee04312478f43388c8ed5837f31c1 GIT binary patch literal 417 zcmZ3^%ge<81SNm@vbF%}#~=<2FhLog&47&Q3@HpLj5!Rsj8Tk?AU0DDQ!aB9b1q91 z3z*NG!$x_4&)KbI(B3MBL8<6nR>Q-)C*R3 zOBhKsIk6-)J-?_Dp&3O}DbRSZX}8$p;}dgo;^S8`dj0MHLWkvX%Q@I&BT$tAIj`5 zMm_1!gP|7%3h|{Sf#OO;rR}Yxw12}2bP#h2w5gq&+w>GD^v%kOZJE$(51pNP`{uph zzL|ORe)~;6uOVpB--XSC3_`#1$*5(IlxLrUat~pI1s8dOC3vDGdKoL@NtPsVyXa;; z*^*N|<0_tNsi`ixIZv}R0g32CgtMO^EE8=H)_DkH*epHuDd1Dj_zax8iDtB?96BR0 z`Fh~Sp3jtz{D^E2%H*37t@#^FU2!5(u6bleUu-p-uUZ*wBp$&VBG+5q= zqoC$jDe;IOJ$(m)+~^2Q^<&p{)?Gq*8o;1na?6R`h)H}wCh=%sF04D%ExR7nW4JLA zu5~Uj)wX@dBeu;n+x7w+yIePH`%dh*M;^ttaZm+w-nJvY%+OAGO;HI16Kk0A+hr1W zF{xG!e5Qo~jqHG8LaEH5Do14eV4G=h0@wkzoro&jn&pQMJLnlq(DT`q_bTh#VHD$9 zP~o16Q?J3OS73+44J%dncq5>Vg?fYP@I@+k`0!g0%@@x=noOk0!NoV4pFGZ;+nH!7 z_sc(COmfS;+;Ts++`Kl>&7F5!Q?04p3wMiO6z|80KHt;l`}%xyW!x7f`dm++>+5si zGcUC!c9pi7n6o`|wr|chSBEyWJ>7n*JKZUEi;20|GZ*{jVsrISM)}J-AMZ|lFDJ%Q z&sgdkOU)1XL$8eX|36nC6UZ8ICC5wmIt{k*39|h5=+XW!Umuf2=hb0XIVvpEJWu6$ z5I3mFRn7+b3KyJiESuu!CD7OCWp1A0BE5iVt`$dO0+g4O(wqOCQc@D5)H6zbqja*A z_#xJ2@<6{kuH#m36R&a1)Rd(u8(HDlzYtJw$itIH@DC|#0P_~G1Js8XkalcYt7hMdw-PG zZfxnKLl1&pWC&E3w#mg+u%J1*kV9_iaToR=<`gJxW9Y%fJp~G#Sy_!OI}M$knSJkl zZ{Ey%`_2B4OvWkP?7xMz=OK#vg($riITQ|7u<#89C_rnJPD`}TNQ@qmLV8#V>k%oU zvl2@aoYA5>Cvkxs(qejCiU)F7OX$4B(-cG9q(I~=3b2sh#{2Ey(QQ%^L~m1RZjY#G z7O^)>&Cv}MT`+983N6Imwk_3IMd1S6v=KL_*s!4L5XEz*1=Uq!5mwSP;w`8twrU#X zyJ`vR;T6XylJ|9`42y?*1uyncIrxJn*+EL80VOejmO_A$!VCo?kOd(SYKQwy8YLJW z9Efb=wL5rp8(`bfZ3bKL=r$=9#EGARB)U7`nFm~7oDh!FSDho?vA22)#2XI|#QS^` zZNBe>scvMDJb|2fBO(UK0G$ldUU%&erMbaDB2+sm1STSu{kNrHaTtAZjrlZg~`s03M_KlQN&hl z4O--GplH#=SI@95F3?DBvI-CvWJM&lY%8`?M)CV9+>nc=W7sIJskjb-Y(?=pi~L?t z$S^lh99Iu#0AvNbbrU7B6(b&D5*|f@*pI0LY@%LWoV&WTyiv9tpqfjhpi4?g#iO)@ z6NOqiuuYUIRuX#$6FF)53w$4I|301Ys2d*b44toi{vwvDk2InW3%f&ZY}Sj-`mx#C z^$tH!&owSLE;rxX%09@phFyNr<0pN7vNqolhUzPg!ozu2$aq4=7c#Y*UE7`JT63*6 z=3ThrU%2vY&J`9sVZj#`FrFH&-*2ootIevLx$2E&{juyb;HDP6)S{nStbN)^4%WYH zmMz7=zmQ(kh)Pfpcx9r0{qq#13At~lZZ(n+xX=hw< z+7qXJak}S!1l!%*wV!VORDD`?#k?oxeKB9l@3Rztu70f1D*5x4zsJ*lh^FZdm3RM7 n?@$-rRtDE-)BX7cAq*q)j$4|SpPZ&3KIAS`{Mu^ literal 0 HcmV?d00001 diff --git a/api/app/models/__pycache__/user.cpython-311.pyc b/api/app/models/__pycache__/user.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1445b9519c609ddf85aab14b7dca0b4b10b9f86e GIT binary patch literal 1134 zcmah{&1(}u6rcUb?j}td18EhZimhPNLk~h*Q3?1#{Qy1KdRYR?HZ!rC?rzfAT}y8f zR0>`q2u2XGml$afZ+aB}f)siPb1Fz%d#mWFAo^z0R9Xe!%zN`be*5;#d-Eodh#?^V zXK(SdfY29ibSbi@e7^(AbA%BVY~%>K;E1~DNV??6x-4+NXh$4HS3+H~RY%h`0g31u z!tz6eBSfo92(18jNRMJ=3T4!7Zf0brTq)Us<1+Pz>yvwgGG)rAmV1wBS52QxTMo$x zOfCd&o}ZUZkL33ghgEz5s455OIT{khw4yy3|PaFI^2E* zxI=(en(85RbRVr9LMzQ^U4-v}JEX_LzxIHP7ZY7?9h8->fts;H-}K@h=t`VLFJZ@W z?|Os=#{j+cZh5Qvc;jhp>se!S>BHCM#%5!A z2{Z6ZmYb)udKv!*f#CR&*C2{DZq%EK&CHa%~l zM6oezdb3pFSd~L0x3s`wP&14j8>asjeFrz%J#+PZZf3#r18kLY#nK$fnPm&OoP)B6 z?d5pt(efhYk2w@Po%aYtWq-Bh!InJOPM@mWT8}1|`m5^e>5u7FG`kwju0^wz%k5;} z(*0_oTBzN5T6|V)q(4Sl$?R$}yOzvWuD8?2tCO|y+W70C7Z+Y$c;DAbPpqaV*3uJ| zTkX`*YJW{@3^z_Uhu@AgM_Q?|)zsKpYOHdTFM6U|*X>M<#k_gjwDYsXS^U$dut#Al zSnr?sD5#y*#NoE1*n}R#^QT%jA06OYnEoVayV}Lhpt5ubO#Ys|2OxGNK@i<?sYWKI=FWfRT$qve~YU8jeCFmBNUeS8>D?QX#fBK literal 0 HcmV?d00001 diff --git a/api/app/schemas/__init__.py b/api/app/schemas/__init__.py new file mode 100644 index 0000000..d8df8b0 --- /dev/null +++ b/api/app/schemas/__init__.py @@ -0,0 +1,29 @@ +from .auth import LoginRequest, TokenResponse +from .category import ( + JokeCrowdCreate, + JokeCrowdResponse, + JokeTypeCreate, + JokeTypeResponse, +) +from .joke import ( + JokeCreate, + JokeResponse, + JokeUpdate, + PaginatedJokeResponse, +) + +__all__ = [ + "JokeBase", + "JokeCreate", + "JokeUpdate", + "JokeResponse", + "PaginatedJokeResponse", + "JokeTypeBase", + "JokeTypeCreate", + "JokeTypeResponse", + "JokeCrowdBase", + "JokeCrowdCreate", + "JokeCrowdResponse", + "LoginRequest", + "TokenResponse", +] \ No newline at end of file diff --git a/api/app/schemas/auth.py b/api/app/schemas/auth.py new file mode 100644 index 0000000..68e3aaf --- /dev/null +++ b/api/app/schemas/auth.py @@ -0,0 +1,11 @@ +from pydantic import BaseModel + + +class LoginRequest(BaseModel): + username: str + password: str + + +class TokenResponse(BaseModel): + access_token: str + token_type: str = "bearer" \ No newline at end of file diff --git a/api/app/schemas/category.py b/api/app/schemas/category.py new file mode 100644 index 0000000..d62e7ec --- /dev/null +++ b/api/app/schemas/category.py @@ -0,0 +1,35 @@ +from pydantic import BaseModel + + +class JokeTypeBase(BaseModel): + name: str + icon: str | None = None + sort_order: int = 0 + + +class JokeTypeCreate(JokeTypeBase): + pass + + +class JokeTypeResponse(JokeTypeBase): + id: int + + class Config: + from_attributes = True + + +class JokeCrowdBase(BaseModel): + name: str + icon: str | None = None + sort_order: int = 0 + + +class JokeCrowdCreate(JokeCrowdBase): + pass + + +class JokeCrowdResponse(JokeCrowdBase): + id: int + + class Config: + from_attributes = True \ No newline at end of file diff --git a/api/app/schemas/joke.py b/api/app/schemas/joke.py new file mode 100644 index 0000000..cdf6a97 --- /dev/null +++ b/api/app/schemas/joke.py @@ -0,0 +1,43 @@ +from datetime import datetime + +from pydantic import BaseModel + + +class JokeBase(BaseModel): + title: str + content: str + type_id: int | None = None + crowd_id: int | None = None + + +class JokeCreate(JokeBase): + pass + + +class JokeUpdate(BaseModel): + title: str | None = None + content: str | None = None + type_id: int | None = None + crowd_id: int | None = None + status: str | None = None + + +class JokeResponse(JokeBase): + id: int + status: str + view_count: int + like_count: int + created_at: datetime + updated_at: datetime + type_name: str | None = None + crowd_name: str | None = None + + class Config: + from_attributes = True + + +class PaginatedJokeResponse(BaseModel): + items: list[JokeResponse] + total: int + page: int + page_size: int \ No newline at end of file