From eb4ac8ba574f3e59105aa0008bf14324b3826235 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 24 Mar 2026 15:17:45 +0800 Subject: [PATCH] feat: implement history API Co-Authored-By: Claude Opus 4.6 --- .../api/__pycache__/history.cpython-310.pyc | Bin 207 -> 1688 bytes .../api/__pycache__/images.cpython-310.pyc | Bin 206 -> 2383 bytes imagecreator/backend/app/api/history.py | 55 +++++- .../__pycache__/history.cpython-310.pyc | Bin 0 -> 862 bytes .../schemas/__pycache__/image.cpython-310.pyc | Bin 0 -> 1461 bytes imagecreator/backend/app/schemas/history.py | 18 +- ...t_history_api.cpython-310-pytest-9.0.2.pyc | Bin 0 -> 6859 bytes ...st_images_api.cpython-310-pytest-9.0.2.pyc | Bin 0 -> 2197 bytes .../backend/tests/test_history_api.py | 160 ++++++++++++++++++ 9 files changed, 230 insertions(+), 3 deletions(-) create mode 100644 imagecreator/backend/app/schemas/__pycache__/history.cpython-310.pyc create mode 100644 imagecreator/backend/app/schemas/__pycache__/image.cpython-310.pyc create mode 100644 imagecreator/backend/tests/__pycache__/test_history_api.cpython-310-pytest-9.0.2.pyc create mode 100644 imagecreator/backend/tests/__pycache__/test_images_api.cpython-310-pytest-9.0.2.pyc create mode 100644 imagecreator/backend/tests/test_history_api.py diff --git a/imagecreator/backend/app/api/__pycache__/history.cpython-310.pyc b/imagecreator/backend/app/api/__pycache__/history.cpython-310.pyc index 2abe7f52a29ee94cbc97e4c285d80d32d76def74..cb84b261890116b39467abe08325f12e970ddc21 100644 GIT binary patch literal 1688 zcmbVMPj4GV6rY*>V|%@J9NS6Lv_J%+UaR7u6sI5p*X)mkh zVH8^0&uV!+s$060t>ulVVd-+Vo;RbWr7Kx0Z%1uP1U)9vhS)gV zeoSEwkLifCs`PwhuF^z6mkA`UfhxNJ$E7JN~F;}LxyTAYV{*Oa3(P=R@zS4=F zstz@!J)sncfOH?GO5^(U>4ST)`UgVCd;nAfso_*gG1l=^32CjC>-zU%EM$V)?t*_I zXP{hLkxzu06k{a}0byOPxHvDk$V_;3N5lAF$S{M|=fLX1xC=vl0@Iu>h^8lW!8AQ| z=H$>lV!(O8`HRvC0lIubUa~m@FlfJ1G2Zj3kTV&Av++l1W)Z>gz^?q6zLAWnX@R}JSHWwda zhY7w?py+X#W=^Y*Cs! zCzPT$6c)Y*dqlp6XI9>tvV0%(Hetjk6B=+D7I~g(`2lLMcCMt`TH0JxLyVAo1SSgM zdo$yJg;ahFihk#|DUA}ij7ci7XCxMcJyl{Un7VqNCE4(q$Y`zRmawZWcjXE9I{t zo@pk&fubeqAxv8&r1l4-mcP#$%x6Az&l$8AW8ryN@g3mLmOMLWPIy+YzbR{+{R26_ BqX+;1 delta 159 zcmbQid!DgApO=@50SM&G4rLkx>Bk@rGGGF79Dul33`nFfq%h_%mQi_ diff --git a/imagecreator/backend/app/api/__pycache__/images.cpython-310.pyc b/imagecreator/backend/app/api/__pycache__/images.cpython-310.pyc index b262bfaaa6feb92789dbeeb3c4e00ba00eb44e23..182aa549ab6dc6c4432986c4a56d553826e6bb2f 100644 GIT binary patch literal 2383 zcmZuzTW=dh6rP#A+Fsw{OX5;Npj>K@9E4E0s30nFXU_H7T5iH-0&N5({F0M6RpH8zolh2YR4VFqvcZ6jaU6uj2J#Z{u*1m z)1zfpr$LHcb%6bI+M~&u|Lf6M@>roQ?ePk2 zZ=rtYImC_nrYv3Aymlj*2*#!JB}>_uX0m$q=FQEo9*$Tl!elJ%Oax+*^|5reSeAhb zM0=NsA>9V4p`_7-b2b*kNya$n%|sH*Cy!AQsl0Guqr3cIlmh3DjY?7{4Em7%X;|y-uxEu1v)3!f;yJNQ%ROPmQx2 zd>AK`Mbe~!2&A_hoFsI6WT@m79~*uZ*M5U1OJVo{3v__?jp_Lrx`QdcOL%i;91)lq z$9UfymtkhA89Y|nqvV+Eo5G%%)HuZ7qb+12;p}~c(Y}Szv?5$;QcIL(Q12(`DWUcu z`4LlCePlhr4^ZE^F3W;F6d!~tdlEq)jd@UXnCc2V{}UrL?G%O3saoF&!idpN*Pjtt z$xA#OLDo$zos90$>mvTVdd%_a`F z5y{emUEEZ2BNM!D^A(VJOAT$Mb$~>wnzA&Q35c>=@bXmo zOR%Ow(&aw~NnVuy-lF{7dHF$O9+PX(Sgs-RGw7ogE zhcy>SV)qb`0pEe<0K~DVLtWK?_Mu75Y^4XUYJq{lzSKiAg@kDtsCWw`i{GLZVI9?| zcZ{jiLr)N`J~hTbDq1^q_MI6ys?VHb42a~Yaf~n$O~A;p;B>TpXcRxR}*#RI`2TL!e0~@FNWiEB8Iwt!|h8Su5)M(A!l@bC*kW$ zJmNi_ey!O^$Gft$@ZkWY=-w<^23+&2VFpatlU9C%D@#C7!but>0nIjE;Eky{0IEv%HYyu&z0Qm{h!l3oEk3k9yaxtz*zpf>w1Qg@~@2vzKHF=$|V;QLa+^b_oQYO*Yh)g zy52u8ot*&MSQ>Hy3a)yz&KI{plC|t!6hx!jEZ!R=Jm#uxOHZXo_4w@oIN&T)05YH~ z&A9rTAnQv>R9xZe&da9KW(qLK2D%Vjy#{oD delta 159 zcmX>vbdIq;pO=@50SIKx4rLkx>Bk@rGGGF79Dul33`nFfq%h_% diff --git a/imagecreator/backend/app/api/history.py b/imagecreator/backend/app/api/history.py index 4d5194a..85c443a 100644 --- a/imagecreator/backend/app/api/history.py +++ b/imagecreator/backend/app/api/history.py @@ -1,3 +1,54 @@ -from fastapi import APIRouter +from fastapi import APIRouter, Depends, HTTPException, status +from sqlalchemy.orm import Session +from typing import List +from uuid import UUID -router = APIRouter() \ No newline at end of file +from app.database import get_db +from app.api.deps import get_current_user +from app.models.user import User +from app.models.history import GenerationHistory +from app.schemas.history import HistoryResponse + +router = APIRouter() + +@router.get("", response_model=List[HistoryResponse]) +def get_history( + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + items = db.query(GenerationHistory).filter( + GenerationHistory.user_id == current_user.id + ).order_by(GenerationHistory.created_at.desc()).all() + return items + +@router.get("/{history_id}", response_model=HistoryResponse) +def get_history_item( + history_id: UUID, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + item = db.query(GenerationHistory).filter( + GenerationHistory.id == history_id, + GenerationHistory.user_id == current_user.id + ).first() + + if not item: + raise HTTPException(status_code=404, detail="History item not found") + return item + +@router.delete("/{history_id}", status_code=status.HTTP_204_NO_CONTENT) +def delete_history_item( + history_id: UUID, + current_user: User = Depends(get_current_user), + db: Session = Depends(get_db) +): + item = db.query(GenerationHistory).filter( + GenerationHistory.id == history_id, + GenerationHistory.user_id == current_user.id + ).first() + + if not item: + raise HTTPException(status_code=404, detail="History item not found") + + db.delete(item) + db.commit() \ No newline at end of file diff --git a/imagecreator/backend/app/schemas/__pycache__/history.cpython-310.pyc b/imagecreator/backend/app/schemas/__pycache__/history.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..965d9446b0416496ea8324e5421812bf66401deb GIT binary patch literal 862 zcmZuw&5qMB5VjL1O|z|1U_s)*1N5@Jqk>kj5^$hMKrgvi-rC!>h~r>8NZsr5GQ0+l z;VUOzffHk=(DGx;GvCbEo^Sl4r_&Nad-V9L{Dcwu7L4OYz&M9tFFZPwuYl<2b{8$XtcZ3XR3v+|W}yWY{?9$#*ZfXX>#?w^X`Zib3yM-_8i zr#yi(O>Z9j#qR96Zm;C_{c28pL21jBpwyR?0*}54ctYvNo;CYObp`w(u`}|rcfx)_ z<{o5<;>VK(RJDjiBSmfgG%nfZgJ}7Jb=|^lu7zTDaXp;YS-11~z$GxZ;XM_oz~(-H zd13hi|r?}>S>3p#qPV{NGAsar^1Wj=0r^!z{ CzRV#2 literal 0 HcmV?d00001 diff --git a/imagecreator/backend/app/schemas/__pycache__/image.cpython-310.pyc b/imagecreator/backend/app/schemas/__pycache__/image.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d60bd84a6d7d71fe8a8db0ccd1cfbca582c3be51 GIT binary patch literal 1461 zcmaJ>&2H2%5Vn(eH_2vyDBD8eh=jC+b-H^cZ=-K!5n?uMC1XmvhU>lY`1tW-{ z8Odo(Dej%j$=%qsdpGlP7Bfori0}maN(7TF$0gQqR&nH&3neGvc-EDivN zq64^NaR@jPUBF$7JEHfNjQT&}elnsa*h#cJD22=b_^+xuEsF&A-fl6^r+Dh>Lji2V z(nBzk#8i;j5j1v%6MMpi%%17($wI0GGht#A*78fek><%vnvVT6U@~IH=e$UA$+-zR z&r31Sa367gJWsOA$l>n$!;SremwUUWV?PZzC#nloSo7=oxUA~2%|2B!sY~@Q_>fFL z%R-Eksv7I*k<1g_99XYT6sm$tx4`(sqdv918}wa>Z{xvDFqib-5$Q@#&@Cd_r&ipS z43M)$1c)O8>8=vM9%5(@Gs~}4nO8NoI!{mK8+kmJx;CxKx{U{2kP|a3RXR&S3NECc zs?-WI3Y8BRs{joSnsIflOrP_lD9YNlTyt(~R~1Ed6i4nq3cleK43%W9pFj zv`2^3dKc4QfulF+3kL|gX5~6TU6qBFW&jFV%7QmsC+F-MA9WWJE1a!cOI?Nl)~r1+ zA&IC$&*Cz7AbPV*s}|^Eb#g%$FK$^MgFWi!Uuf1w43vB`+{fv?nCnZ))Bw^eY=v#} z>B>yzX_2mNtUp=%m?ipXt(kd-ie?kjPm5|^bL-?Eo^FnU#q4n!)he0?XcmfhAEKzS zj=-RJ_(muoMizJGF+~5<8JuU^nPy_IvA@tWXqe1Z)>Mj}n5cVTZx!z$1hA+-bB2W~ z^iD>R@v9S&6m>dP4tPwfKB>}TW{De5!mmi7=FNQA=HS>``7KkM=eBE&zt#L!Uf{1w Tqht{bPDGcSfj3|Sci8?7QzI!y literal 0 HcmV?d00001 diff --git a/imagecreator/backend/app/schemas/history.py b/imagecreator/backend/app/schemas/history.py index 5fdb0ea..96b9946 100644 --- a/imagecreator/backend/app/schemas/history.py +++ b/imagecreator/backend/app/schemas/history.py @@ -1 +1,17 @@ -"""History schemas placeholder.""" +from pydantic import BaseModel +from typing import Optional +from datetime import datetime +from uuid import UUID + +class HistoryResponse(BaseModel): + id: UUID + original_prompt: str + optimized_prompt: str + mode: str + model: str + image_url: str + input_image_url: Optional[str] = None + created_at: datetime + + class Config: + from_attributes = True \ No newline at end of file diff --git a/imagecreator/backend/tests/__pycache__/test_history_api.cpython-310-pytest-9.0.2.pyc b/imagecreator/backend/tests/__pycache__/test_history_api.cpython-310-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..491ec6dfb54e5a2d823b1a1cf26370dcf4588cff GIT binary patch literal 6859 zcmeHMNpsxB6$UUE3}zn=7m<=>(Q@o)ypUR`&9NLww!9^lQzd!HI57-PH%U;y%(#KE z#0e&wa!943RLV(J4soi;TX;xrIpmV9a>yY+Al28LboNcBe6KMx1Zhc@>}#l+hu5zg z-4EUUzW(~DQ!W=Y{Qdm7e|Uaf)Ba0^^q+~sdHlj9UDKGxbYE-g>S+WSL({duY-aVO z#%fxsCfCg2Y4~=KZ{}59#xDfLW>M*;Ukb|2veL7DC8##5L9JO+Wy_xk>dm^+bN*y7 z)tpkg?N0|Y&6!|dbDt{b{n=oyIT!42?nk-MJiv47k8B>~2ex$aF3)W~N}8_mA}jI( zztw(cuo5eKI;-3=numCqA7a&8dUKxD*u+n?=41RZUSB`VYtL&u&+9k!=HtA&{+0D7 zl6DxO&L+|BNjAl%@%$>AVf*kr!e-eVo(;C29l-M`_6R$O=hN&_b_maBn0`fT%-^Q@ zyxh=b;VKWK7k!VnBb3T5!QF^EyuIqRISi$choRSL2ktd48iq74x*?a=DvuntjQWh* z?c!m+6{_lqS9qHXH^LjQdSTQN8?v%vdZWWQ`Y5lt;hNKR!|-}XFgZCK(`~gdmJ@ZZ z@pgY|F$%hi5qxvjl8zSGa=#FM=z9@=ZgFu@PPEo|>zWg~0e7M`xXoTBe_Ne)o3|pz z6{{gRw(PZ8i#~Srhb^Po_>nO@0`Vg)(r#)4tzU?>x3PKN(PC{=--5=pD`Wk-*3d7* z`5MjFm1I)B*=f1H%(nbaNONVdTP7kn!W z^0dzz^~=(xP@|aZ*GN0hZ@59%=L@Y)AWe$b?ToZ(6SNU@GRp(k^JSHynX_>`-zhC( z3oj0%c3YRZWIKen|Ap1w*6$eS&TZ@c6HgrJZX9ofh3^fO`E&E69c_dQVdO@=&}jiK z3WND`NyW)VC~d*RZl@h`IFdnI630oLyi4x5ak@{R34FhF3%sob4 z4?FF`;7DU?8Xgl9RBg2s^vVo^N5zONroLVl&UZHy2)aT}I6xcU5xgtVT^A85OQ?31d!8S8 z?NC}i;ZZ1Oop7zw^O1@rGwEi-nxwar$#*61 z96P!fXJ*ud5ZDa&n8Sl^wDCB63JHiTy{;DkkOkd>tQ$YmH+At1RP2HuntfU&1wTgt zoL?M%qFijSEVC5+L&@1L<`y!X@IG!(g9EE30Pn?1yeSgVD%v! zog7trD_)Pgj$m{B_5Nj*#OdY=NZGO?K$ED3;C8G2nw zd0kZCT8ay7|D47S%xQxv%VPGbaSk3ASx_H#Jc4?_^tK`1 zp%zCWc40e46yJuiF}DY4#c^tXg2WPulO*yah&6%dUV8WH@z>tC@X95Hyy6s9ohCul zM4TaUmc(-;zDDAC66Z*~K;r8p&Xc%6;w^~Agu+H~kqiWlIPDU;n#?hwi+G8|B@!=_ zc!k8<5NQBBE?yg365ubq|~jv^fZAHbXkb(imwN1_-60 zn@U=D3bsAOOIZP$6t!NJp^`wLMb%Ofby9@*A$ky}0dq}ht5&$tri0Yw!G6r^vw!#N!V?-r_MR-M6ksxYbA!=S> zMPY~)K(jHTTEGe$<7XA30*lxr@TmlRvg1;0!>4jw4*x#%sjLtc_AxpE1=WZklWba{ zQ-$t$aYc<-9gYYL8;@ARh-DBzLZ{gjI-N++>BPO!iFH={^)Wgvi_Z1-JZ$0(tn>~t z!9vI+F2j1KoThn;4+=9XofsSDC)Ba?#CS>C{%>UA^?35-84G80xa3sz%ea|#cy z?21hyoug~jr*}~J;=E>bts-tid6Pi~Tqc7Hj2RWyi!3*cx{~5CHh2t0T^UiA-xYN| zx>&ISb~dg|6pe~Al%m?^gyJ!8qrR@9?mcKK{t$H~rBl?AjiRoscubyEST!C+-4tr4 zi9?KIU>J2O25PAoSW04G>FzP0jw9Svvb~eh>hAj{xeWMtX=gKtHWlxC zWqEMq6&>nq2Y7E#@!@HImtNZgpoi}@yUrLxe?_l_Bz^$Vcvjk@l#RM($T=rT@+>6j z52R!k1ivn@L^3}%QSM0D)Fnk)$t%+6gtETkB4>oOF}afDlLTdgC8f(FVOXE8L54dg-KXsx5Il9N@>UODw4st>NmjXZ_0pBA&Px}aZ(X?hD&-fWHEHo1xIQ73C3t`YILhij zB9d^Wbhn&hyo<~^Z?`s_QHnfN$Emaf9=Y@(vM~BD1>aAWnbJS%9-|18IvYfOFW?Bne>6cH)^P5rf3=~k>84Rao@vHFzR4)$Y`tRGhHctqd%u0a Iu9gn{57sE2r~m)} literal 0 HcmV?d00001 diff --git a/imagecreator/backend/tests/__pycache__/test_images_api.cpython-310-pytest-9.0.2.pyc b/imagecreator/backend/tests/__pycache__/test_images_api.cpython-310-pytest-9.0.2.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1457433506315dcfd019beb164546ec232cebed9 GIT binary patch literal 2197 zcma)7OK;mo5Z)yziK6we?8J%lR0E`q5Lix~rfGt>%>x07qVOes0K5<@?%JlqS9Yl+ zRwbaVdrdAqHU(^;7ypeO`Xlz*Q~rX10-agfjvSysDeT92tcJsxkF!~`=@GcD-1#$N z4k3S|GJV;g+=r$90^o$xnE2G(t;DtnC5hu#Xz8i?Rq$AGEpdI<*zCBTc)n+3C!R?f ze#6L>xS6#4R?_y{Mz6-RNyqOPxfahQ^ZvY%-S|{;+CQBv_zRQ>kJopoe?~OK8ScHJ z{#ic58@~{LQ7nqi);ZC>M}#Xnu;)B)@)me5@HU@?`$gX2b8x@J=@ZhMe+%zI)_PQX z-w0JaiX)L0pfy7&SRn$DZbYd7LqiFrqAX3=Qz3hnb{;Y%bag`%0Uv`mbk5y_>mo8Yc18Rt`b97lC0M*DNSn3i$0kkUUnC#Gq?$8P47PrUrH}bm`VY{3) zZL8rxHy;d(%}hokRzOciwTFU9A-g?G;uB#{fjz1Xp&3EMb;T6iyl4rtxT}qcG6)oG z3dV&zgGpdEv$RExcA^bc@YG`~bV$weup;76J6QFFKUD6hY<7s$ln z9-kRI5e2zY)WPeGD|=9@pW#z<$b`bOCl(T+*H{~!T88$NomAN2D2YZu+gxTzUK~_d zH)O>=kZwz5>DynSHT(3yT3y|zqnlT+<=ZPg<^6CdbXU75-RP;lDp)a8L6~vjO}eY4 z<5o{;R|=J9sS^9PwqY;A3c{^}7JLgr7AD4R*b2tm`!l*4nomwUd8P_IGZk5T_w#L} zTfn651VG$4kRq2Mqz>KI4R8m8VH6ips&q9*YAby=4NZK5oZGy2PsR0t_O;( z3yh#!4@@pVoySsUQqKqLnM_y_h?jZHQbVf!s_a6O^$b3y%>CnO<&$aUW~r1>KAl!R zd!Kbz%qtzWA}Bin**+UaP&~uO^YC0l#5ww!$~&O_Hxd5;?>i!LhgaU%ygEh3+6gj# z1%v_e88X(7$><%E@jCcRGTt!6E6L~?d76wfhh%K<=KmyP>pe1Vh*U@zv2qcs>=oi= zv0^65XkkMnQ5r3+^lvS#$1q2ijJ;>ev$)ksfOfiq7|U~DkrxmyB3wr3B7A^w72!jK zj}UGm;Ix|>0_ROTj*>aq2aKi~064(#=l%1#B3HrCyR6+K>d7TA=*6HUYrmulP^&M+ z3kmaG*N;uQc4(8=@jun_FM4jB0qEWyIz}*a zv|1j25^G?Fw?4&14#$8