From 7f28fe580d156dbe7c2fd2d88610617915cf490a Mon Sep 17 00:00:00 2001 From: "afanasyev.aa" Date: Fri, 4 Apr 2025 18:16:08 +0900 Subject: [PATCH] first commit --- api/__init__.py | 0 api/__pycache__/__init__.cpython-313.pyc | Bin 0 -> 128 bytes api/__pycache__/admin.cpython-313.pyc | Bin 0 -> 494 bytes api/__pycache__/apps.cpython-313.pyc | Bin 0 -> 486 bytes api/__pycache__/models.cpython-313.pyc | Bin 0 -> 1944 bytes api/__pycache__/serializer.cpython-313.pyc | Bin 0 -> 760 bytes api/__pycache__/serializers.cpython-313.pyc | Bin 0 -> 793 bytes api/__pycache__/tests.cpython-313.pyc | Bin 0 -> 1403 bytes api/__pycache__/urls.cpython-313.pyc | Bin 0 -> 622 bytes api/__pycache__/views.cpython-313.pyc | Bin 0 -> 4290 bytes api/admin.py | 7 + api/apps.py | 6 + api/build_qstring.py | 38 +++++ api/migrations/0001_initial.py | 22 +++ ...diction_user_userprediction_delete_todo.py | 46 ++++++ api/migrations/__init__.py | 0 .../__pycache__/0001_initial.cpython-313.pyc | Bin 0 -> 959 bytes ...userprediction_delete_todo.cpython-313.pyc | Bin 0 -> 2216 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 139 bytes api/models.py | 20 +++ api/serializers.py | 7 + api/tests.py | 10 ++ api/urls.py | 10 ++ api/views.py | 63 ++++++++ db.sqlite3 | Bin 0 -> 163840 bytes manage.py | 22 +++ testapi/__init__.py | 0 testapi/__pycache__/__init__.cpython-313.pyc | Bin 0 -> 132 bytes testapi/__pycache__/models.cpython-313.pyc | Bin 0 -> 753 bytes .../__pycache__/serializer.cpython-313.pyc | Bin 0 -> 764 bytes testapi/__pycache__/settings.cpython-313.pyc | Bin 0 -> 2920 bytes testapi/__pycache__/urls.cpython-313.pyc | Bin 0 -> 1386 bytes testapi/__pycache__/views.cpython-313.pyc | Bin 0 -> 1882 bytes testapi/__pycache__/wsgi.cpython-313.pyc | Bin 0 -> 620 bytes testapi/asgi.py | 16 ++ testapi/settings.py | 142 ++++++++++++++++++ testapi/urls.py | 27 ++++ testapi/wsgi.py | 16 ++ 38 files changed, 452 insertions(+) create mode 100644 api/__init__.py create mode 100644 api/__pycache__/__init__.cpython-313.pyc create mode 100644 api/__pycache__/admin.cpython-313.pyc create mode 100644 api/__pycache__/apps.cpython-313.pyc create mode 100644 api/__pycache__/models.cpython-313.pyc create mode 100644 api/__pycache__/serializer.cpython-313.pyc create mode 100644 api/__pycache__/serializers.cpython-313.pyc create mode 100644 api/__pycache__/tests.cpython-313.pyc create mode 100644 api/__pycache__/urls.cpython-313.pyc create mode 100644 api/__pycache__/views.cpython-313.pyc create mode 100644 api/admin.py create mode 100644 api/apps.py create mode 100644 api/build_qstring.py create mode 100644 api/migrations/0001_initial.py create mode 100644 api/migrations/0002_prediction_user_userprediction_delete_todo.py create mode 100644 api/migrations/__init__.py create mode 100644 api/migrations/__pycache__/0001_initial.cpython-313.pyc create mode 100644 api/migrations/__pycache__/0002_prediction_user_userprediction_delete_todo.cpython-313.pyc create mode 100644 api/migrations/__pycache__/__init__.cpython-313.pyc create mode 100644 api/models.py create mode 100644 api/serializers.py create mode 100644 api/tests.py create mode 100644 api/urls.py create mode 100644 api/views.py create mode 100644 db.sqlite3 create mode 100644 manage.py create mode 100644 testapi/__init__.py create mode 100644 testapi/__pycache__/__init__.cpython-313.pyc create mode 100644 testapi/__pycache__/models.cpython-313.pyc create mode 100644 testapi/__pycache__/serializer.cpython-313.pyc create mode 100644 testapi/__pycache__/settings.cpython-313.pyc create mode 100644 testapi/__pycache__/urls.cpython-313.pyc create mode 100644 testapi/__pycache__/views.cpython-313.pyc create mode 100644 testapi/__pycache__/wsgi.cpython-313.pyc create mode 100644 testapi/asgi.py create mode 100644 testapi/settings.py create mode 100644 testapi/urls.py create mode 100644 testapi/wsgi.py diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/api/__pycache__/__init__.cpython-313.pyc b/api/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa92400314ffd79278a60523535d5e3d0d178ca2 GIT binary patch literal 128 zcmey&%ge<81Oaa@rGx0lAOZ#$p^VQgK*m&tbOudEzm*I{OhDdekkl=CXRDZ^)Pnq& zlGNgo#DdHi5RQ+}%*!l^kJl@xyv1RYo1apelWJGQ3RDj=uNcJm$jr#dSi}ru0RXN! B96gJc7=oFCnZ233n2VUb zSc+J@Sc_N{7-ATMcwkx)bPzv+4P(VHn=(S!Br0TunvAzt6H{_C z^In47p~-xUCA2uT=oVK%QEEzNa!F=>-Yq_m2!ijY$#IJ>B`Yy6Jzp<5Kd+=HGpPs^ zKDXF%^HWlDii=o*oFX<5!448;Db6fOy~R+oL1qjXgIuClPyakDw-Rq)(Pe}w-= zJe37co(dj>=-t^S4(!Y~eBaE@Ox|iW5ZK+g!m?9SmOpq`L7A7%-MNCm4 zmZ%05yQ*98qQ%?-_0zt0&!Ql9yn!>0JwHsHOCEGH8DDch^pwdG{)+nclB!V}v9V97 zYETN&EYx_J(ua(NC9^{5h>KK)Jo2L$=vB`ju`HC7K}X=xx!Ck7YGScxW!9SCwUb5iVLTANL%1u&}{qk&Dxwb+s{{`{m=Jp zQ#H#KS(2ne-?b>$Ulqa*AXPgrmbwsYkm{4B>)^gkjPVCL{HYqaGpYX~2#cyeP>Xx) literal 0 HcmV?d00001 diff --git a/api/__pycache__/models.cpython-313.pyc b/api/__pycache__/models.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..14683360226b692ada24ff31de15efba325f4f64 GIT binary patch literal 1944 zcmb_dPi)&{6#wklPV6+vLTTBmbek#-DF_OaT12M|X={i^%DSmecRM=;FI$FzVE&7{r!C} z-CWLKxW4zEHjNZxf6}JE)E?9Q3YiDYWTv#hfWGpARF^?M%TBT>W~L^XsaW!o*1vf8 zokg3pK#4U~)YM*}sm7XV)Xcm7KF_26K zvME8zQkLS(`>M$ovym-rDL;5hJ2Pb}b1BG}D(FqEoEFM*z+q28QKPn*64?%TYYwd2 zxB0qAyZn|DwL+2Mt`|BhExw5{8X{xczO%+{TNt*D@kTA;M{N5}zd%ggUqYaVa8LWv^J6)MpgAtO6x+d=4r-m2|{A$TiM$OF8W#d}@+F)=xR z!2;fCTPO&fj%U#?Dc5vo9jMPSp=5#yB%iV;dSO>TwWFVUKa3<^Z3#c+a1kqG4tqew)q>V&-Et?{Jw#wu_;aIw+Ch&pbc*X!oB#Y9B| z9uV>jd<;BMg_p@5!6E71IB`^)m{1-jqc_qcXE@z<<4x>4y7|&D6ibDCvM5(0B8>8%XcXGZ=kU>Y}&BbDPy}bC>#2w zE&Z5V1SG1+kwtS2U%Uh(hm&hoPLv>LrXkxw(0BJ6qYP#+aMh zDNa4Q@Zf^K70Gi%I6jIjQqZ)N*C{q bKP=rZ?K5Qe^O|)2-i?RWed{lVY#iD@4AO+x literal 0 HcmV?d00001 diff --git a/api/__pycache__/serializer.cpython-313.pyc b/api/__pycache__/serializer.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..269daf2963d6c67b65df315284e1ac98323a6b4c GIT binary patch literal 760 zcmZWn&ubJh6i(*XuC?v9*40%IRuAGF-1gFo6fc5@mKHSL90=o1b_t!`S>I$S`Ui;M z#Y_JP{~19%SOPtH+M6&HufDgLby*DL%lDEm-%DOnZEUPDY~K$qhF@{~Nx`CpHL0E> zIcI_ie#8zr@GcXc@Q=JhAN(%sum?;8cbNzi{<68)yd3v^#~~a>abre7%5K{#`_|K$4UIOrve){>Xp$?VvM=l; zZrY}l<8-8?v};n1ifoz_UzhUjG|lUkmXrexrOEYJjSDG(Y;A~YmD^~bRi2f$EoEs^ zqx&*72K1Y$Q6)-SD6OzFd;i&!1k|KRaKWS#olsxaxHoxc13EO&dsBvT9pMAJ*t+>K zwA+tAMQ|G@;0^)Vp2QJsQLs&LgJ6eXF1SUERBls;SYrWH?Ara0=Y_p1hTw#xL1ViK zcuF|{tj$>gr$ArCM)NC|?*6S~y8rSCo&9P`+dObJeG2!`fPPU)<{9 literal 0 HcmV?d00001 diff --git a/api/__pycache__/serializers.cpython-313.pyc b/api/__pycache__/serializers.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..70e2ce548fb8d3b7ba41c48260ca1c8496396fcd GIT binary patch literal 793 zcmZuvO>Yx15ViL!(bCcuifB_&MLnSIrJULWAGsiLXw?evbtP-bI+4XT8^&HC_yGus zb0z))zk=Vu31q1!PT^E(i?}kAO$ZgNXvR>*eK`;rChp7+&D~or3un&Pe?P z$r%$&@FRA}fp?kkgn#56`rvoj2HRmG=r9qc{CRtxyqNd>hC?`vlGcQRgu81-fzAs3 zR)LxDW-WdSD%X9h%Td3{X)u@t^)8Y#mNMXifhRcl)8ZZ$_xHU<1%U{#RG36=ec>nm zRGX0775iBttGoZ$r)YH#Py38RBz$NMgCumD|FhjYRyLbZ%aXu(I(Km&RAyB!Gwb4N zoX>d#%2b8@#7>g7YfCxGPL-4{mh!aBtAhBFl&`9+nC+}cInZEip+{;|N(ofNg{W4A ziw0U1xpB9oG&ZxkkL4`r7nM~8rK>2daWJ>@_A(Mn;5B@q)lS2InWKv+<$pq z*t=v1jgT~G?5<;%tQ-I~=XD7$f!>gdre`)y16Gcy0gHQW?5~z|?T1ZMd$5fL^vuj1 ggbSZ@e$MWmv+c{k=e>^)zHS|S**f^iFqrO6?>Bhc+pO;^rZCFhLiUf(6T2TG{8wcgpUH zkUr(9xRBC>V%*1;KD7N0{0HPAd5TRM9G3Vg5OAJM)x3A+&a&i>g`4~B%+Bo0Z)Q8W z+$jQUBYL;^RwLvMZo13b2c0PZYs4d-HcMtSu9Xn$v-*s|4ZwzH&YCk8w@Rc)&JxcW zA)Z~;CXK|O+lwjJ*~N{kDd#p5a@rRRaQf?8H>R5b3*|1{jaIWF7_TLMi9`dgP6@;s zsS>VvgzKKh4No5--1H2PmS@5>mTRliw>YZ@H5o)9-n5HF)Ve_c6CFOxtg{4Sjm#g| zCSi}OLYfDlfg^`mN`WF~X%D~}a8kx2M^<^i!~JSc z^Yr-kg4q1W)dBeo@1D`qBtB@XZ`QSJBGZ<66&}#J<8RVXgxS?w6hoo*(pU z65Q=q&mX##n)`n60L?QIZZbW>=m%C3PlCn7y?WT0o9FtaN zD-u!}LUMi@_d57xd;t;U^}B7qsWQ+?*%q`G)tPb<%Z-o^!C_bDSb%aMWGe~<6IffR z#0OD3gq^3!xX@mH>XRb_aPl#H?P4Cp1M({W;rg}5*S7QLw({pT&tKUXelq>ke4c)m zex7}neeq3Y^NVjcDcb~NzOm}OadSt(7)>Ba9H&_2fow?|9CExD@jHnnd9aWzYl`^6CYO8)4!w(&^HoyM6#pCyILBfH d#GavP+72o05O;?Z|1%x!(xdO*6Zplx{{uhDF;D;i literal 0 HcmV?d00001 diff --git a/api/__pycache__/urls.cpython-313.pyc b/api/__pycache__/urls.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..39809bb3ed20a09b58b0dfa079d4117db2e9c595 GIT binary patch literal 622 zcmaiw%Sr<=6oyZlOlRsSq9_cgP-a&V1*w9!A}9#;f_1=!j>zbQI$GNynJT(-rw`ym z2tLfTT@(Z2!j-O+zJN)owmT0bIr;PDKPPDo4D^AFlk?Bw0|Izgo8K@xN$XiAkKllV zHX)A~N`sSd@Ma>98O{?%@*309;369w;^MvjUxV&y!(3WUv_7Wz-K&qo7h=W7Lc2en79qa97<5c+}Q<$aPwx z9nuW{?sGA8+O|0EYN}k>yQE^UNTVK|-;Q=6KC@h{2L57rkrP9H+q(zd$r!@)&%JW7 zGF@dQ&amuUXjigN&NP{`q?&Z4>K;E<2f~!3d}c&hnLj~Go`D!!TXY!>D{e%2cy$1A%v zQg|VTk|&$iY~7k|SlM`Kt46k^9H-K;J>Rr*bvxIvSL2O?8ae#Z$zbBnWW%z;58q#- A`v3p{ literal 0 HcmV?d00001 diff --git a/api/__pycache__/views.cpython-313.pyc b/api/__pycache__/views.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8c1e868580309afd83278774402164c0d20f01ad GIT binary patch literal 4290 zcmbVPU2GHC6~6Ohd+a!Nu#-3@K%5XlOoE+-@RKYdM1U3?$g&`8XO8HYP# z{=}-N4^?O%Xr-b??F-v&)$mjv^9bUhJbE@%M$@3JR8)yRMNL+s+n1g* zmJZTGM9)?tHeGTa;Ot+gTP&#;q|FHqjFBk>PkU1`IIJ8(}%n+ z1*6vblL-DZdF8fDr?TjwN=}&Id#o)1gA-&_CSBE$BwL%-COzb0i^z_!Dw|@Hd`(=N zh}`H!LNYCcfZkOT*Cq!lvtE*h+q6mK8~gIX?SRI*|LR(M^pXAify#TxOw>7bd*^4m zKBtYw&iS<^L>n~`<1$-X2hTgb^Ke?^1ycAvbNmFMiE*X5gfl%qcIX9|}y znk*G*9(~xisNvy8A`x@j@zG0Eo-16^!8L5>68>L@%hh6Yx6DrXC26j9qtY}j%u2ew zJGvEI;8|%&V0Xz&|M1;YEB?^^J3qU#aLT}^zq$NnSEu3XT+o(XJugA``MuA7{^OFc zTDhIa-R2FI{`m@#pPNw?FZhI?gToJ}C*GtbtdOMOLM1fUMy!KOmO~ zWkf<*k)fQ(LK^TQM;$YK)Uh$bj#D|K%NVY2f?$^27&{mTR+M=_`hcVue3Q+T#1)%J zWU9BUvgum1B{6C@Q6uXV3z5pG+exZjO;vv>XKnYcbf7A2xcj!Mwmzm@q7!!S zPPbQO-_`Qsi0B$&BP0#`wkaL1&Qk8`o*LajRo4se9U&U0I#hm|bd$8VYVRVME<#kH z?px&2Z~``^gsO)jM&w1u2&=JOfWxXVA@o+pX=a*?ab0AZi3(Gus|ctiDLKeZR>_$T zD;1S>2*F1XZr~M@7P6_B*8wqkTy1*lnG$U_`CLZNP&{6WNMX7Pm#@fKNMDDd%d?u5 zJ`~TFV!1Fm00)X!Z#uJ9$Wpv7iZ2-Tn7k(Er%hJ{0%!zPyMUR@Rg<}H`YJgo*)U>m zsqaLxH)%35?E?c1_X3GuA&M7Z@^b}EH^X&Ut|v_lRjp|F4`7hxf$*;fe>qqV^caDj zha<~@z4NXWfAIdDdw0tIF2mpT@KDL$Rq_wa^Q%rWxc^T_9vvwUj2Q!CF9yb6gp*$l zjDIow@Pj8GJa<1m`rF=x?%(tp1LN~PBb;32IroPvkq?)qmLroT@Ah?pv`5NqyN$Np z<+hm77Aqb6s06(2)Vya!XfF#p3}HuE*kuU27KckXe)QTOdeJes_@m{H!{v@KqhoB@ zf3zeV{r6fM*(x$`!DCB!jWF;t!On#r{64$b{pECN+up}nBRKjO@92M4InaHp?SWT) z+U`9bbUy8KA|Glx9wyJio)awhY-j87G49zR2IpfA;E%`@!m}i)nORwqOpheZ7IMWr z&b^X!t(eJIG=52%R;Z@u6;)OXl0^68>9kKPBI=e#f}I2Gv>kuhDl0%Rv3!&nTL1K_$jkW2mIy`1?ZTdjJp9X%mTTHDTWi zlZ~vnnic{$eiIxz2g8QM_}4H%(;awu+u;*WjHq49ZdW9e&vo%VjC zy}#TZH`?PX!R~S}Y6PR@;E)jt52*foPOo(v6N2<&M)v$LVE%q9i2jl*I%Gn+uT@xuII4)=QvWu-ySq!iT_S zf))ZAlXpBos{joHX0O#S^pXuN0(J&-S4~$XW6skaaCqB2RnQ~Tg`%2Meg#NLcY-kL zwhFtICicxDe4CtFxM6zg2?s?!b6vK(0q==|tbwbOHz9$d{DzD<2c~u<$G#Ku!>-{@ z+mYE>Pmua8#%$#4Vls2cU$qe4{|GT5TJ}Q!_*FYGUwcecalI-?~X_eGXBKRnwchl2K<0 zG5CVZYt*_%Clq@b9xNop5>i1x=m;yHwweuo*p1p#Z%!_`;!e0>gT*mziW1 WLhA&_^=$%kj9EDJ4Z+cZivI%g(0p?M literal 0 HcmV?d00001 diff --git a/api/admin.py b/api/admin.py new file mode 100644 index 0000000..c47772a --- /dev/null +++ b/api/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin + +from .models import User, Prediction, UserPrediction + +admin.site.register(User) +admin.site.register(Prediction) +admin.site.register(UserPrediction) \ No newline at end of file diff --git a/api/apps.py b/api/apps.py new file mode 100644 index 0000000..66656fd --- /dev/null +++ b/api/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ApiConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'api' diff --git a/api/build_qstring.py b/api/build_qstring.py new file mode 100644 index 0000000..f724f6c --- /dev/null +++ b/api/build_qstring.py @@ -0,0 +1,38 @@ +import urllib.parse + +def build_query_string(data: dict) -> str: + required_keys = [ + "profile", + "pred_type", + "launch_datetime", + "launch_latitude", + "launch_longitude", + "launch_altitude", + "ascent_rate", + "burst_altitude", + "descent_rate" + ] + + # Проверяем, что все ключи на месте + missing_keys = [key for key in required_keys if key not in data] + if missing_keys: + raise ValueError(f"Missing required keys: {', '.join(missing_keys)}") + + # Собираем строку запроса + return urllib.parse.urlencode({k: data[k] for k in required_keys}) + +# Пример: +json_data = { + "profile": "standard_profile", + "pred_type": "single", + "launch_datetime": "2025-03-16T08:47:00Z", + "launch_latitude": "56.6992", + "launch_longitude": "38.8247", + "launch_altitude": "0", + "ascent_rate": "5", + "burst_altitude": "30000", + "descent_rate": "5" +} + +query_string = build_query_string(json_data) +print(query_string) \ No newline at end of file diff --git a/api/migrations/0001_initial.py b/api/migrations/0001_initial.py new file mode 100644 index 0000000..ee34459 --- /dev/null +++ b/api/migrations/0001_initial.py @@ -0,0 +1,22 @@ +# Generated by Django 5.1.7 on 2025-03-15 08:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Todo', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=100)), + ('completed', models.BooleanField(default=False)), + ], + ), + ] diff --git a/api/migrations/0002_prediction_user_userprediction_delete_todo.py b/api/migrations/0002_prediction_user_userprediction_delete_todo.py new file mode 100644 index 0000000..e62cc82 --- /dev/null +++ b/api/migrations/0002_prediction_user_userprediction_delete_todo.py @@ -0,0 +1,46 @@ +# Generated by Django 5.1.7 on 2025-03-31 10:14 + +import django.db.models.deletion +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Prediction', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('result', models.JSONField()), + ('deleted_at', models.DateTimeField(blank=True, null=True)), + ], + ), + migrations.CreateModel( + name='User', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ], + ), + migrations.CreateModel( + name='UserPrediction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('prediction', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.prediction')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.user')), + ], + options={ + 'unique_together': {('user', 'prediction')}, + }, + ), + migrations.DeleteModel( + name='Todo', + ), + ] diff --git a/api/migrations/__init__.py b/api/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/api/migrations/__pycache__/0001_initial.cpython-313.pyc b/api/migrations/__pycache__/0001_initial.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0939751071650b9a52ec3e2540c52228b58449af GIT binary patch literal 959 zcmZuvO=}ZD7@pbPY_gk8n$*^mP=aVIB!_;09$KaJLn>C=L&uXW4BPBvJG$A8vy);y z6$H<{6#5qg4<7pyJSG82nNz`2Z;>coolP3*p#wAfJTuQb`@YXRgG|N*a;&ZW@YWRo ze#T@x64zj`D#0m00Ku1F8#1`9Fy$VY0rvq?iU6rL+|$QFH{ZwV2s72wDv7I@R1{%0 zsK*>m!ypoRBXo%$)ox+{NMDn|R|!sm4H!g#DF`wZDNI`cEMe<=+5baESSF()%}(u2 z-g>4W1tpMQ8!J%y=X}6E2|Ruvj9S=e`b1tO50WmaJ1w6}kF{Z(UZ=!&qc32$ zk`*aDybNPuVk~WM`9xw1+(Qs?<%DF7k!T{Pf9TuTbq4s^{AGa{CQ#2dqb=rZx3qNruv1!V=hpj4Z7TaKku=P{YE0^%w%LPm0=u%?hWpkD zyl~##A9^;lX_R7I;YeGSNTi;QTC&RKB!zNDvvTRH5W>GYfR*2R4(canFIVp5%71_) G!{~pK%J^6S literal 0 HcmV?d00001 diff --git a/api/migrations/__pycache__/0002_prediction_user_userprediction_delete_todo.cpython-313.pyc b/api/migrations/__pycache__/0002_prediction_user_userprediction_delete_todo.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cff1936e4963a5c2cea6672613349924a876d2af GIT binary patch literal 2216 zcmcgt&u`mQ9DjBkH+IrA+0v$Ix1}r9MmmvpteKQ$0(Jd?*0KU|J28l4x%F#in%e2J zQ`DW1kT~yx)PI2k(so)o(IZDY98x_FAaNR}RE0a=XD4e!%RoZHlApid_x<&G-|zQ* zebV1ABY4KQeye^fBJ?X`x=*-6oU8!xHBykmEhEDDU!L&r<(ETC0uh$NBs_+O(Ku2< zBS;Y{LOIrTa{4WV0-A_bE*E~un3Wt)+^n~K|(j%)VDsS!f)4s$|zhN9vl zfan|vDf|>igi83lXbcM==_@CCodxtbsz~M3*?lFfi179mg&AInfbGy(9q=nEQjr4< z`866*Un2$@!{_-ZbT+|D|7*O6O1#L=@Ka%BpveF2ITQcooKxIueJ6e2Bj=p~^1!ln zLAm%Z^Ob^=UOLZHWuQEEcE8-Me2=I+-otdr^2FIaWl$MnnN!mLW6a?o=9Hjhl#!d< zG^dOfLr}GAXYoN7T~aO=xha99lq+Pgn$3+-=|T4MY{H)w2ndithnn1*9$ zH7b8dux@Oy`$Bm`UtG-zv`@#ITBGLB2#6eQy@qMDPK<4h?5SILk4iQsU~4?VRNf$1 zbFi*zPL887t>IXzX??D0x=!UrT|bpYx-u#fY%}jN+)doEc8}d4yF< zw{n~>`Ud9G5RIrl5LKnJs={1q)G*L7Ro!W5H3kv50ae{Ji0#x26Pp$j>$r|h9h(~l zwh0?}G&<*J`~jP6L|{A8+S>j3MV2T4-Y|3;X6p>?pNH(P8rwLKNlVHHD*+k1XH;jQ zQ~@V1S_B(aa~Vo2>Yr(5)uOzCCc^DOwd|+eLWximh;{IA~Q@a4-1uEDf!** zH+WEJ)=GiDyG${1H@HLZkavNF+9R7?$##h2xDyd^SARm$pV6DYi`O{usoY9Tc!`NW J5HP-vKLINT7`Xrd literal 0 HcmV?d00001 diff --git a/api/migrations/__pycache__/__init__.cpython-313.pyc b/api/migrations/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..620db1b35846eb0ad6a72ec8ca9ebc7c90b263af GIT binary patch literal 139 zcmey&%ge<81Oaa@rGx0lAOZ#$p^VQgK*m&tbOudEzm*I{OhDdekkl', PredictionDeleteView.as_view(), name='delete_prediction'), + path('api/token/', obtain_auth_token), +] diff --git a/api/views.py b/api/views.py new file mode 100644 index 0000000..803abe6 --- /dev/null +++ b/api/views.py @@ -0,0 +1,63 @@ +from rest_framework import status, generics +from rest_framework.response import Response +from rest_framework.views import APIView +from django.utils import timezone +from .models import Prediction, User, UserPrediction +from .serializers import PredictionSerializer +from rest_framework.permissions import IsAuthenticated +import requests + +def get_prediction_from_tawhiri(params): + base_url = "https://fly.stratonautica.ru/api/v2" + response = requests.get(base_url, params=params) + + if response.status_code == 200: + return response.json() # получаем результат предсказания + else: + raise Exception(f"Tawhiri error: {response.status_code} {response.text}") + + +class PredictionCreateView(APIView): + def post(self, request): + user_id = request.data.get('user_id') + user = User.objects.get(id=user_id) + + # Передаём остальные параметры (кроме user_id) в Tawhiri + tawhiri_params = {k: v for k, v in request.data.items() if k != 'user_id'} + + try: + prediction_result = get_prediction_from_tawhiri(tawhiri_params) + except Exception as e: + return Response({"error": str(e)}, status=500) + + prediction = Prediction.objects.create(result=prediction_result) + UserPrediction.objects.create(user=user, prediction=prediction) + + return Response(PredictionSerializer(prediction).data) + +class PredictionListView(APIView): + def get(self, request): + user_id = request.query_params.get('user_id') + created_from = request.query_params.get('created_from') + created_till = request.query_params.get('created_till') + + predictions = Prediction.objects.filter( + id__in=UserPrediction.objects.filter(user_id=user_id).values_list('prediction_id'), + created_at__gte=created_from, + created_at__lte=created_till, + deleted_at__isnull=True + ) + return Response(PredictionSerializer(predictions, many=True).data) + +class PredictionDeleteView(APIView): + def delete(self, request, pk): + try: + prediction = Prediction.objects.get(pk=pk) + prediction.deleted_at = timezone.now() + prediction.save() + return Response({"deleted": True}) + except Prediction.DoesNotExist: + return Response({"error": "Not found"}, status=404) + +class PredictionCreateView(APIView): + permission_classes = [IsAuthenticated] \ No newline at end of file diff --git a/db.sqlite3 b/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..5be43ec85a075149993c2d6f0f0c5c999240687c GIT binary patch literal 163840 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 literal 0 HcmV?d00001 diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..008da0d --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testapi.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/testapi/__init__.py b/testapi/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/testapi/__pycache__/__init__.cpython-313.pyc b/testapi/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c282104d508732c0c884248078cbe5bd0437d8d2 GIT binary patch literal 132 zcmey&%ge<81UmOGrGx0lAOZ#$p^VQgK*m&tbOudEzm*I{OhDdekkl<@XRDZ^)Pnq& zlGNgo#DYvX9Uq^Wmst`YuUAlci^C>2KczG$)vkyYs0U^-}~OY`Q9&PS}Ya-&-RNS-QQ?`k+V3~oJ_Zn zjKBkry@A(EvNc$RN8l}$!82N{X)Xj;_NkF^X>`r1H6f?UwB1Vr5vA>`cK{3V^aI|G zpaqh7AeTHQjh5M*HFy0v%nEzPb0%$!-?|wi4;wQ*3*&juE`xNuoGf(nRY#lek|3E- zy-9$8{S|<44pbVN-xDY+aE{3a5pkFE!+{^oBP*PDLYb;4j76MqE@>9+>>T)VFBDNA zm&tcuCP^gxcy^_ocGBxdLWw}qe)T=-$5&yS`%1}he}IEvrrQ{kC4wRW{gxTfhSLp% zFEDoRT)35Uw{mKnxle|>$8*kas3jI&g%RFwLPbd literal 0 HcmV?d00001 diff --git a/testapi/__pycache__/serializer.cpython-313.pyc b/testapi/__pycache__/serializer.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..adac9f779d3d3258c1b24d98470ac6e5a389cdb6 GIT binary patch literal 764 zcmZWnL2DE-6iy~Hvuka;t#x%3ghf!CgWFzuk>W-0(9(j&n*(9o$u7a!o%Kx?sXssj zFJAg1{4;`humpPYv^QZYUVU$8w##B5U%r=o`Cjspa${qSVf%4#KKzE`FA5eds7d)8 z$r+PO@*{T0fp?koq&V^p1&A)|u=`B5VMabH z#`P9fcK7#OR0f@!e(Zy$GK8Kwk|-m&RjS!I!g=JR;sXx zHGP#>3+Bz#>H?)Ll$O|;d+_W@40@8sxL}isxf+*s?oCdePX`BjbIMYzBYb4%TQ@%i zZu{})5N_iH+#w+AlPH8O3bqMu5bO}l1-FQis@l{c)>r@)ymtTVc|q@zAyh)rpt0Ko zJgFK0*5`c=Z-Ksv3+LA^sv5M8sRqkutn61)y5>Pu*Qam~4d^EoM1Bj-`2~A;!8(_| U;Jq)ef429&xA*=q4CV*<2a`gt%>V!Z literal 0 HcmV?d00001 diff --git a/testapi/__pycache__/settings.cpython-313.pyc b/testapi/__pycache__/settings.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6f91e0b3aaf596ce3464af8e6d2eecacdfd34160 GIT binary patch literal 2920 zcmb7G&2!tv6$eO)-=t`owi!8gAuD5>N(@?(8Y0vWlyi2JbScAktxQJBO~gv84XNt7A1@R%h@ct+uwLNSs?pg|Gj>ynSzyDUoakupm% zC{3~`gR*E5<*8>H5dv z&@6!#koSpV;6sZXc*UQuc?I%utpjY*MV0K!jty<1bO*XZXc#)D6!Y#(yc?RT>iAG0 zm=Eftxko(m3kH+Md!2W0KAB1S{0ttAWizPKhe4oI49nyz!Q&T99kS0?V0fb8!x_^r z=W_8kJDZ09YpA={4H|g{IKPQ$sb|5BartLZ_s`jcu5}MyDBS}f6aU?|e+(_#XN@z1 zOHXLZ4~Xt~<%t&;8@3Ki<@W%NO?Ap7z8a8Lny4L`58CGkR|bxCAt{SErHFTX-pz+r zyo&b*J#Y0RED8P|80UJQPi)^exnI$9Jo}aQHs*}qSMeOcR9A}7*p^UvBsQxwQmu6m zjSKCz9L!>^wp431kyo4+?9l0Hykgr><=_ZuOvU@kKzF@sli2FsS^aFwaeL7J-|I9A z%?|BN<5L-ptgUZs(u8hx6}=CJG_rYbW4#omQL(vGYl<||6dEw@BC$i`Z2_UDtq$b) zu!SVJNLn35dO$^MTf@5Q-I%+Fc+18noE7hzpl%-k&0F)_69&C1uD8Dp%L!n9Bow}suhB%{hhu_4HnIvhB?K9vf)(nGN+)hdGDkYlZg z=+ac*7CVg^LNmH%sYqk83~xkPrZF4dJG!<ODYN0j78;-Bb3RovR$p&6lGZ#@;OvfqM;W@}9(fd~Y^7(|neTD4jip9&q3 zraP^cB=2_Wl~!|`CM2=Zt_u=moO_CPYQBAavKN}D3X+he_{|mf*MB~4Q4jSnA0l5zt|L>l2 z8^%$XW!ckEl8yYY$grQBMwxW(Z}GoAc#~Rwom&1^YUNF8^>u3XO=|6RYHb)FWtnV; z9VSOnCXpE~oaFMu%-dut9~x%gF2%DU&=i>5^ z?%60D0(d-Fv}YHOXBVCE;!@_*&?}}my2)H94l^g|3&X@oYH=7pf!w2`G?Tpo`6ijm jo3EHW_`D{tC-L6_^i~jI6J{&X(@Y{C`b(DFgNpqGau(1X literal 0 HcmV?d00001 diff --git a/testapi/__pycache__/urls.cpython-313.pyc b/testapi/__pycache__/urls.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6930a4dc6369d6b1b558fe44e13c960204310f2c GIT binary patch literal 1386 zcmb7E%Wl&^6dfm%M;%H5(GY6)Se`+VvjZB@W=v* z9ZR}E@C*C_pTLsR1;P?y!3tKOiamE6n+60Dcrm_n=ghh1o*8>*33dtNV7ne$+l*9#y%c4wB3m-vt zv6WldlM!#fSN3klS=7jlqGVsGRe;^)hBnImvNq8wtyHsJ+wUW&kxp#guAI&%JUd$D zKVtzid0Mk~Dx`(Qj_#DPi#`Gg`t6nL#Nk25>kb5sJRXn^7bIdbqM=7Z!Pl4*nYwVWkk(L5mP+nU4C8T)YDvL$*4WweQnzmkG5p zEG9hG5X0TIhGiI&Qp1XxOQ*+tYQ@D-05n(~<#0kRs!M1=sthf+RXWBhb;Fp9OYJs< z?RLB~bp_0fgtsd4AU>{)Sta1#ft*uS~^*d{)%rU&2DPQ0tl vzpc%0))ro!+Q64o_Q0F!?7Qm1+v>ur-bVH6>&^zg{dJ-+m3v$f(@^vW?Rb!P literal 0 HcmV?d00001 diff --git a/testapi/__pycache__/views.cpython-313.pyc b/testapi/__pycache__/views.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee722e2595dfcd53351d42e42d8288a2fc6c48c6 GIT binary patch literal 1882 zcmZ`)&2Jk;6rcU{uD!O?#*h!vWJyv}_u!;OL2X3iQnwWBG@vZul1QtKy>>TscHNnE zL!urK2b3d1s-Rq&s)x2v3641;@((0LDAklmm5@NW1tpabz3^u3O``&%^?PsTeavrW zely;S$D;_^ALpM|w?u?~W1X-`En^RZaSIv9;EJfgVNPc@U*rn{7Qhw^u_zWKECu6I zQ7%MqB(UY8f)$9Biz-$@M~cxx495bWQq&4@9M@4N>PLp!jg06_d_-u@i4#>h6Wd{( z3`b>byJZ`LrBrR##!iXsa7|a@Bd_ckFl5!7r65Er5YL^oN!@daJpnmt1J`V~!JRH{=?MGAGB<%dlZKQ?E6?@T?ILW4YsTtBR z8fjJhp9p#AAi{`bc~_c_heZtK5UxZx`a%OPDa0_$g_bKD>Xe*7Z}M(rx-E>J3^)|_ zni}#W2U*Ir8hWRc$#BQRARDa(4n_+UaWTfXId0V`*8Ccfo22vz27-(n6Ltsjso!(+Cu_y`Cp zGVjvhRo}0Z(V?MAZ81xHZ26vRHGHRJWpQK3syjnBPUoC`R$Qav9MGRiHP0#&D$aW4 zMVe#?F52t{Tw>5LqbL=swvQENN#(|T9pGU5dc!6@p|K`FlVwo#(kCUm&iGCRm^>4u zBC%@~8fk@7(ZW?iN&nrc~t&>?%TQ5)Mj>U{djKkwe!p4k5gw>dsY+cM=vku_hreaSU90-%7{&$#d)a*pFnR zz4)_M+!dJP`FLt>~>`pdDUVCMmP`GjG zFR1z(`fuomgtV8os(R?HRsKM|Bq{jddE@b$_r~&gagiXm*1mntK464?R>^GDreJ*R zzAB2n&RtxS zH&MGo6D0>cqXVU>1!GykX`$5#BsL(VV=25XlmSES5a@)!gkZ-4C^MANT&1T1o(LF$ zpd+UFO-ZsGQrhpcq7Xb`mMhusyM8a6O0G0eE}dY0Q=m$^=G@Q$7qCVR02x|an9VRu zRbqnlgvm_JJS8d*L58hhBOIzTtHKltq0V!VHas&K56SOp%x)8x4>PcFbr#>TQLgOl zJ?pj);%N8isMBpn@vDQK*DrT3mZsAO2CU^WGtGKgk7H*cj!RFOa%o~DNSyzmYO8%G zRMtU`xK^?xj+nxLoeEnn+)@09#+9S;(e`FfL!o+8q5rY!6%^;?{MO_#pX!FY?>-1J z>u&qwV~qcLbzB=iK$!eO8{d)lj$D#!wEPJzU#$dJ>(9TU?H`TRFOA2S3;Mnz{R4fL BvugkV literal 0 HcmV?d00001 diff --git a/testapi/asgi.py b/testapi/asgi.py new file mode 100644 index 0000000..b3f8740 --- /dev/null +++ b/testapi/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for testapi project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testapi.settings') + +application = get_asgi_application() diff --git a/testapi/settings.py b/testapi/settings.py new file mode 100644 index 0000000..641c282 --- /dev/null +++ b/testapi/settings.py @@ -0,0 +1,142 @@ +""" +Django settings for testapi project. + +Generated by 'django-admin startproject' using Django 5.1.7. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.1/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-np(nxnh6mw)v4pa2n2z3pl_5&!2z$jshhak9r3v=y1u9rd*sl!' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definitionЫ + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'rest_framework', + 'rest_framework.authtoken', + 'drf_spectacular', + 'api' +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'testapi.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'testapi.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.1/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'drfapi', # Your database name + 'USER': 'postgres', # Your PostgreSQL username + 'PASSWORD': '1235', # Your PostgreSQL password + 'HOST': 'localhost', # Or your DB server's IP + 'PORT': '5432', # Default PostgreSQL port + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.1/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.1/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +REST_FRAMEWORK = { + # ВАШИ НАСТРОЙКИ + 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'rest_framework.authentication.TokenAuthentication', + ], + 'DEFAULT_PERMISSION_CLASSES': [ + 'rest_framework.permissions.IsAuthenticated', + ] +} diff --git a/testapi/urls.py b/testapi/urls.py new file mode 100644 index 0000000..52a2cd2 --- /dev/null +++ b/testapi/urls.py @@ -0,0 +1,27 @@ +""" +URL configuration for testapi project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include +from drf_spectacular.views import SpectacularAPIView +from drf_spectacular.views import SpectacularSwaggerView + +urlpatterns = [ + path('admin/', admin.site.urls), + path('api/', include('api.urls')), + path('api/schema/', SpectacularAPIView.as_view(), name='schema'), + path('api/docs/', SpectacularSwaggerView.as_view(url_name='schema'), name='docs'), +] diff --git a/testapi/wsgi.py b/testapi/wsgi.py new file mode 100644 index 0000000..e6b51be --- /dev/null +++ b/testapi/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for testapi project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testapi.settings') + +application = get_wsgi_application()