From 1f2772b15cce1904d47f6d364b49ee0964296023 Mon Sep 17 00:00:00 2001 From: ivanLFN Date: Sat, 26 Jul 2025 17:37:57 +0700 Subject: [PATCH 1/2] update:17:37 26.07.2026 --- .../static_dev/img/image-holder.png | Bin 0 -> 10633 bytes .../templates/about/description.html | 7 +- anfisa_for_friends/templates/base.html | 4 +- .../templates/homepage/index.html | 2 +- .../templates/ice_cream/detail.html | 21 +++-- .../templates/ice_cream/list.html | 42 ++++++---- .../templates/includes/footer.html | 6 +- .../templates/includes/header.html | 74 ++++++++++++++---- 8 files changed, 116 insertions(+), 40 deletions(-) create mode 100644 anfisa_for_friends/static_dev/img/image-holder.png diff --git a/anfisa_for_friends/static_dev/img/image-holder.png b/anfisa_for_friends/static_dev/img/image-holder.png new file mode 100644 index 0000000000000000000000000000000000000000..55e7e4d2d88a307370d611b91ab029e814262f29 GIT binary patch literal 10633 zcmdUVcTiJXySD|8s329Un9w9r1*Df4dPjPP15!kU&>^%aB1jKiK;TG~E+{PoI7fPi z&|44)CA3JWA(R{MH}A|h?>qi^=YHRw$y$@&e)@Wzwbx#IML*M1r@qa0`^uFo)S4P9 zhF7j!2mbm|UMC~lRY#WOj@4Jy+}8-|>>FV3?Q{j=2z77*YP#FII2k(GJHotro#e?x zkDuuns}>X#Z14U|N=_ae8VQ8KR#w-iXXZYA`t-fM2Vg!@ieS{$%P-ymAF{g_hz!oBu@qMfI=#-}rt5L;lwk z&_)2RUJ1Vfr2Nn3Kaqb?{j2{szTd#%SAHYuH!xYuZzTN&{;dKaCHUGEimOj)|Fii| zi>=JH!#K3-$?omOcwJSNxy-AtKcbZ7{wLJYp;R--FyMB%lqg?3DAeJP+nt@ z7=mR=mKco{x>}a#TCSfxqooMHZ;_cB&R!R@|K82b&n4^$C4Cc{ra_S{HC}D2lQyZo zfONCUbk~BCKA>^bt~8vTV<*)!)iV;Pk?N7^hgY*{XwNAFOFv-zhn6CGAigiB$|IuO zST5Fw7c52*%{TwKg?&kjcWHb??^?@!mPD8L$YgE`NWSNDDk)3&%M*4JTIKI{Gy&zk zLa}7LbuOMZCd#LPMhdB&R=@RZi4uZ<-tAmqi8)RR42VTXa|FR{S>AI`!~z!sUSXXS zOfSAQ>&w8?vi9u%q1lU~yx~Vdd?+>ai7*wl{QQrGP!2CvurUQO%afZ!*^3qXVo_Q3 zJ(>=C=X?Bia`C3(7~!gfa1m|3F9i&*m-2DAZL>>)aY|8pbvBVx1xHC3DiPm5KHnX) zFtfNA%Z>QskaPaCa`vY!F0V9GFrUV8xy&!tJqF7hy$d~~DZea9U7wfV_~9KX`!d-P z%Zl0)0Cs@!N>DeKmO3Is136rRRAf0S&HpE5*Ur7XLc^a>c&D@c039Kqoc{8?H1az3 ztN;7@ak7QHF}r^^9{qh}QLwAD>?^I0O!N%EpBC~-QExUpn*VgMjyEF|9yA=r@cyzB zO-$-jF4Oo!AKB(BuaCT56he}38fuSxINzGRY4qTrWXSWRN14ummI6`_chJX$@caGb zx&KHum#;2(FlB!vVs5xS(vIkJv*Q3TRR4mmh`YzROwCD^H3;~EUS4Lx#G--<3uPZ) z7!j*wm!;$mxa2aB4M%yt9@lGl^6Fq+voYZCW{lNAN7V8l4`YU>b*Lo`Yxh$}MHC;| zapoR$CEaVP8yeW~WN``bUqhhAZSjcq(5uIknl4F`2bpw)wyub0beLBh^djgzBfg@C^*oTf&I zKCaeHU=?FIsgOHy5DPgu&3GVXZFHG`l-Ua8Pk_gPNuP|E0Oj5kSWSu6k)iT|C1TH; zcdFPL;33#V*JC7JBKT{hmC}!=H$4AIp0q2?MS8`fEBD_!Gf)tl1o6X5YwgtRF4dNf zUf084amj?ymxCoG8|gl8b4NU33V$^~z)ap@y0d^Z0!(=OI9j|)D@a7|fd7bPr**VS zpIW&26^;4UwuLW#t-AS5MxxF*2gI(^Yb00iP1akxdh=jpOSlV_R8Kl$6|Sagkqne@ zrBt1yOrEaub>boC)n7pk${i(fArB8Hv%kDq4+y_^Z|bP>uwA9#Sfy;+qGxy9<2w&I zRMeUk$a@7%rJGeCSW;S=kGnvdg^L;M>^l+ecv%_!?>Z}Sd}%g6?0?C0g1x=wJ(p`` z1LcQF26`K1oYb_dMDFqJG{140*TwpJ=SsU2zV2^gx=OCYndAzQ=_(C=CJ8O6G_9_CkemN zTTQVg*6iiPmUogP@M&JrNc&d?mv~^E8cetMRlw7wP`FP0wNBLZ9Q#_n`{`(jH6dC(re^|H*K zZWqnhAls&td%WH&TCCBrYj~vkfJqA2(-H4oTVDy6Z4wb0h`LG00=C1F8C79pPqhGUKEJ~CRvwOv5(Jv%97-; zut^D!|iIJnlk3b5U3}ujQzx5vhhm>~Sm<(-*t;nO2{zp>Q9U-JIdf6REdQ``~ zu|G8Z)DYDLW86CpD#u%ei>Hkr;gO>ZC6%K(aH3fl*4ltWNn+jZg&-}qKOwQJEq@Zg ze(LX6C3^`<37+!&c=pnJI^d}(Yj{WoKzFC@RB?YanQ+D)cLOFB_N-fqIjr{nqSTZ& zb2WDl^XQ5C%fsh@g6*?d9!-2N7P0{ldF)@JA?T&S7~W`1ayxSgw|q3zHe3W0+0lQu zx#Rdr+l4YbMAyH8hz(lU{rVw~rhPYFz=!pU*+WVK?>NqF@r%EcRR@O#A{Ny7ZRGRt zDI?fZG#1O7L`fkdb@~tc`!b*Pb_cyDFG(kuebU?gB*B39PZ9aVjT-VBV&| zw$15Lc!+i!M)v##+c)V;&D~{&P^o9k6vVrhustPFh7Kf{zbEwV)ErFE0U<)wmXJ+7R;=0o{3ggg^4T12^Y(KvOL)jFm;HPWWW9-_ z;B6KtpV=h4PHpK-%UFTtg#L=(;-K&=?d;mA>NsYDIzzIIs!@*AG*P*yd)?e z?y7T77FANMkDO@kzqRt)XI475U+L3njdkwCN24pLo6(BFau#l)t%`nr zA94cdqQDBmcUXj1xAl^qoQuyaqaXCja`#B7<1Pv=u}QUEXTz1dt3rAuNIObz@$w0| z^^cM>0J;u&O)K&uhBJ@#Caf024;|R4^QZ&l{Mit;fql9uYzgl~d}H#dpog@|Y8_M0 z#op}EVfL*1CvnvooN;kWnf_9hGszjY!qSve&MX3-?C%QUaCD;I8V{{V_m4iEjn&=< z12v>I550C-Agz2_4cYe=ydRcoErQ;T4-e5?TG5Y^?@xZi|dv9MMPE3Tj3!FsUC`qyvP&#>cMGW6ILFXqT1q2YwOT6ZBr-z z`EM2H#0$`ZP$-O~ta&mP8e$=&r94v;| zqkx&`z!Qg5+v1}SBQXp-x>JcSIAGBup2=COK>z(PlT?q;%vfYmYU(gSu~p_vafTFl z&~b2^8~a1S!s5C6`Q&{_>mx1rD{C5Rpf(^N12bH^)hCD_xZgW(jsFL4ew3$1o*U5S z4t@f{s<^|@SF`ZMs`sTfNc&*~^6h%fc2Ma@I&69VLHA!zmD_)K6V@)kMdcKlQagQ$ zLA2hB{pFN|Gy|mg7VW+Xb>3>IH8a-K5vF|ADHhoMAg4?hB1S>vA4sCLi9y8vTpJRw zz!c8ZG9hCl?%LeaM0XEX()Vkn1X5&L%|Eu&9%kc995i;j7MUrN3{$-;q=B(k=i+TUgQ)G9}}3YlFi-c9*`({vq&6q_S*vL2$5LyPA9dcP+@+>x-VJ(zVFz> z?zeU|1GcuK0wTQ>oxKSPx-ywsWHQAq4w_Pa_S(Y{8rFd>lw|%K$05AS#!U zn>7Y>QykC?^a^SLb`Lo;&7QV*p!?YqfoiE35vl>nj$)gE+A=U|;fst-k?c319|wMU z^8=axG?LCo9G&i0U2Re~N0|NoNdOn!X0O^@!^s6XwM2S#XAv)sENo$C$JMx1g^Z(} zSG$xl2QL|d`N{FWQ{bBk<8yT#GRB*VR=pG)Xi(@6+hA#-EVp@hZ!B!b<_&OBt@udJ zNZbI~)EKnW(9&F3;|Rql@^rft>x?2 zZAch(=i$sMrov~(g^PuNfPkBJb~#d$KwbG?6v?TyT5i zm&NxB_qJE#b!kNtX}?|_)xo^Vp6}t~-U-61wauQMR5Q-vKXCN~sNsgTIlrkXC1 z%VW}K%wd7FM6=zfp^p|YUl6Jj{&CPOXArcYhj}$Dqx&gzMRSS#O*?>1R7hhvF{gxZwCAOF#{DU{E$7cL0}XQE3~o7q!~d+3 z^mV2wM;T7^Yaf3RF9`w5>SuN7AMMJ=n-?c4r@5;L=yEZ1Y$FT>w9Lf&Ne+{bdbOk! zs%!N_cBc3)tx|&)RX*&UW-Y$>2<(|s!%cEiCIZgJ`7=MGE_#PzE4F)L&cyAAyNuWP zXJ9qeU+0pC$yLiUSR4btQ-~HE?B)_4(rPf!9<{r;i(R6 zgvX#4G!B5(N1vC+b(9Jf5)t{Lb~lA-vD%^l$O}M$uiNu>`{M3>BluM+?dXuqFfi0* zvq&a91e)rRaJ0ZIt(diXeo|M`d~7ZG?c~PcPHqdztNKZ_F5>GRefFWTz2)5EM|D~r zh4}6t2v1KE2d8j+un5#Q{H)y4O}+bEL6Mx{G)b$K`ZRBosxC$ap~fw!np=iL64^Y% z4r6cQx{*VPB);nl9y8asYE+}kGNdFS1E2-)2ixt@{$`^$&!F9{Na@g$+|G?-LKmNg z?eI2RuRm^e;nS7n-4d=)^+`S6fqc>CygL-cWza%q>^11hJio+EG+d$I>f^u*aM zKfij^4Y{ z58aqL@*^d4d(Wx{UPK6rV%~=-5jzE;k|{r0=&&m(Mn~fDNlvf=2A*mc!=jlK?4XD< zEEYqvXq*oYjF=Ap=0ZW-1hp{LJ-F2*natzQiaid3k*?X>jeMg{QoK$4`OEs$aA|?R zKd9l<`w5Y^O0~^am)&jyh6!x&ww_wl=q*AuSMmQOI=2812wjgf+8UQcTi~qyDF=$fya9ujUZUYL?I3E&O>kl((PczuaH_3{`PrvG;0s8JoIKS}UUt z|EA_@I7CTUm7hdI^ACh2?`^%AV^-YW!43Y+E9d9+cONM&B0!xfi0PcTBuSaS6syEN zOi%-9NRI6(f@o_|$9bBtRnCN6hD=F3$Xn=jg%8h};`-arypZWHubYPnT38DV<&Byt z0o#14#W#g{8>@$l(}q&G{?Sk|z3EL^nX~Pm+ZU0ishEawd17yOiIMGvHHe$>VX@qejEM=4Rv*GtmU@+qlbhp(0c`X?^~V# zS;VPm>-G)ssib{|%3rdj-rgxiD7!1bSX8+_F;_dI2vGe zpcL^DdbEP%{Kg>WF4^j4m1Ed2b2r$VUz4x%q>iMY998<^Pd8r+49kt00$+b%{quNhb(5-7xiR`s==9k5p+LN|S$}IU-Qv+cH-c$;r|LkHhCw6D#3>w_?qZzmx%qoFP}=vmmwb0-0x7cZYMc4Vx^ z8_@2Te)no|$h2G)6|$27BQGcStQzysmS#+QP>tyN>f2(W^^c)hI7vpEg>>s_b@Mks zQ5BplLlNJn>zWm5msV#V28Uv*?@!K*iQtR$J0@7|<&q5;D<-p=M?!&x%o3_HP_0bWz^0bBLMjbMz@ts) z0IBR8j;TohQ^5??&9UIH6XH_P!OEUK|CZQfLOk`}ZHGy;L|nu)JG-NM&hVkghyD5Ni;34_g_+!1*>Gfi6!oHTmZsyAXYoYEjEsk6E6W4B8v z6g131;~qp#=^=z$^}+#@pk8EV>G-x!v`9aD3D8tXVLlA``6zz<*6NdluU6`>6JU=< zh0O!%ESMhYAE}%b`&a1s2}L>iyiKhY<#us|)sd>HAP&*!LG3tgF@fm1+Kefi@j)98|J3UZ+doym#`8bj(`A%)w437l+ZLR@=8vlEu z@h830F({aAqWLh9sQnBc^I~>C~>X$I5ow^Tqssxc8~NRwetNiiE;N%B-I#KSg{tCZwPVE&3I6-y5qxYyfFfv zmTe{E#F|`L3Xi+-UWl{DaYH$5?dJ=q-B{Mn>OE})1;pV~D)o)1&ZAbvi<27tW70+p z(j~3T-zvgloD-TmsY(Cto<=pcn3pK zHIzy)cl((59MbdU>Z_&HgsD_H)35VJs7qw#*#1?^UE9Z zTbTP*+}7Ju=EDs>*8WvN{QPiN4N8{mjMLeljxZ7_t^Sm++WfR)ro-IT8@H^4c%Ofe z#;GBhw|Jf{dis^MS1e}?v-et0#Q+(X$VlGl)H|I!q+!dqkMgf|ecnDnOTiiMx0sPM ze8~4w04}ZrN55KTqF73s3(P;5tdxQ52EiD>a=VV!7N4D|LeAvU9kaipmcGP^XeF8< zP__-rUyy&>cb884XA|EF5y4l%jCp*wOodx!KJwGmbl0Hlr za$dK710;vhEdh~MU9GG0=pkR9Xtu7S>tSMc_Ee%+{Jk3B)=Qk5?U=cu!CiBm@gmRy z^wo!IdE9u6$e%QgDWtj-ypS zmiGzj53O^kJnEw@hzsgb?s5y142o*b7#Pw?8+7m%`9G8uW{j6eT_0Hq*PWw1EPvmR zhzkw3i~**n<*N;P4&_DNf;})*>C=dik$vQv zh7HGJzs|Mh4;I!6(P%oJT#yY0RUBw=cFA~{Z@p_H7v$aQ`atqXZR2wcYP{R7xIet( zh*D`h{FQliV}+))fs!;_LErE&m!~<}8}}zGeY^6YN_RI+cX_%;EV|r9q)#=yE5-^z zIR9~cYGCZOB)@0xhwtrOZ1z9m$$UZ+tZsTdJv^Wz^y(GMMd8O^3A4i&ggzwL2t5zs zs-iBhtX|i&O0)37Bx&#ed=V+%YdaTzc9^nRD(ip)7*8Kv%GTCC#_cWtSg+D`j<7w=so?#XK&A32I8i1|#> z4@#n1CEqC7>lmEU)DI`{5_?BF9x~WFdC7D4$`5ptt>4KsdSF8g`ijbQXo) z=GnF>3AMJtZs?;u@mgD<3Xe{C(urfB*nKbsr&gPdDru`K^wddrcB@6Z`UVV4B+V#2cXfnKRNKW%X~bJ2;2s{^rXE>c zG__%tT?tDyuf5rBg8+n%9)iDG{W_eIUO?F_&(F7Kf%J@P>aV5a+zZ4r@GXvZ`_;Ze zARZZPc0m+`MnLDddL*>+H0Lxjsbfo=KxRGq_+gt@)qsa%BsGnasavTBIoDzq`mHXM z5rGB1bqtrnd2tOGsIT1jIfJPlSC%vPP#{?EiKNIqwv?{fE`IXkwts#((zV(xdHuYV z!adO|<}>F0!*=?pEeb8tG8Ve`p@VSTcMX!S_ni1p-a@=K)aGxWI0nb!Ycfx$^oLT6 zj2hhJMT22QgLFJ=Ae(_ZW8cLy7GTNoq=4;?sjJ?$VjNGKa{2np8wI|a7|>Hhe=r;X zcJzKF1?SRemq62v-)#-O!KAXWp=N*d4q~g9qIuuf@5TY?jHat22HI%;R0K|B7-2u- zXEEJ;Q)!1%y7;56NP5V7^kI#+O>4bzN3Ve$KDEE^9$m1Lf`u(bO};N_<)ClHt=IFf z`~5K_Nz(3L>{3+vY^bbBiM1y|kw7nXoIgAlbs}q@>|#>xJuP0y!Ts>kw1nzi7pLgQ ztf|3kkmUsQdN`tTVxthWFp?Jb3{o}x&NiSw`joa6ey#JuW}Q+g)uXenQ&MVkM0#4a zwXE`+`sybUi;^T%CS04AhX7h=b!hUVnP0PbDHDfMFkC^^Hw8&*w#jDHnE#5 z#CgOC8F(Z7QxgriG`081U71D#Pz6_6SN61DlyS-pgh}At&=i8SnI=pJ!{`bxIX@WDRvN=( z8k2&gglV2GGTy`DBDw(Uab&JFm$|w@+L%R0PcY`(zGa~zpx~{&go#C&&1tj6Q>oIk z(C;(!kbFMz<3xYJw`U6*!|@92g;;xV&OD28q&xmXOj>?lG&8D&ROdT5!b$cICa2Z* zD&-smO!PY5L#5X7cb%ClJvILj*X{B}9~xIOhO#qN0G&Yuau$Kv8e;Fa!! zxmK#gHz-Hq;|b}eyrflC1dS>#alsr+*@6oFz&-ZGy_MR}p%~HQ8){Rp~&0rVHYXCq>F%_H~bgt#V zt6$s7 z{3E9T{FJt^WS(=nvFuX{ZHZv4o!1H`<P%*{S^x#d!}{2JIDjb2#$OyX27Q>W^@ z3Q?pl>PN0Cr~n2=IIT`yzEeL%>=+=&>T=A242Q_@>8)}j%LjO**~fO|Hz6&ZK1=%OOD)aU&a zC4_Wu|H#!U@048*ys_~GZG_dN)6zeVyglpd_E#YnpE*@!ET(~q^FQXF(tZFXAK!sc zlC5*TFT-bD`v2Yuum8QXV*lf@AfJx=%>lXJ!2ch`;(x}}ALeJwe_oL^9_PF{P4|v` Q^zn+Os-8-f(x2h~1pw|m`Tzg` literal 0 HcmV?d00001 diff --git a/anfisa_for_friends/templates/about/description.html b/anfisa_for_friends/templates/about/description.html index 373d14cf..37b2f5ba 100644 --- a/anfisa_for_friends/templates/about/description.html +++ b/anfisa_for_friends/templates/about/description.html @@ -1,7 +1,10 @@ {% extends "base.html" %} {% block title %} - Анфиса для друзей. Описание проекта + Анфиса для друзей. О проекте {% endblock %} {% block content %} -

Описание проекта

+

О проекте

+

+ Каталог экзотических сортов мороженого. +

{% endblock %} diff --git a/anfisa_for_friends/templates/base.html b/anfisa_for_friends/templates/base.html index 6219c7a6..9a61e2d6 100644 --- a/anfisa_for_friends/templates/base.html +++ b/anfisa_for_friends/templates/base.html @@ -10,9 +10,11 @@ {% include "includes/header.html" %} -
+
+
{% block content %} {% endblock %} +
{% include "includes/footer.html" %} diff --git a/anfisa_for_friends/templates/homepage/index.html b/anfisa_for_friends/templates/homepage/index.html index 3d2191c0..059f0f48 100644 --- a/anfisa_for_friends/templates/homepage/index.html +++ b/anfisa_for_friends/templates/homepage/index.html @@ -3,5 +3,5 @@ Анфиса для друзей. Главная {% endblock %} {% block content %} -

Главная страница

+

Главная страница

{% endblock %} diff --git a/anfisa_for_friends/templates/ice_cream/detail.html b/anfisa_for_friends/templates/ice_cream/detail.html index a6af384c..97ce7694 100644 --- a/anfisa_for_friends/templates/ice_cream/detail.html +++ b/anfisa_for_friends/templates/ice_cream/detail.html @@ -1,10 +1,21 @@ {% extends "base.html" %} +{% load static %} {% block title %} - Анфиса для друзей. Подробное описание мороженого + Анфиса для друзей. {{ ice_cream.title }} {% endblock %} {% block content %} -

Подробное описание мороженого

-

{{ ice_cream.title }}

-

{{ ice_cream.description }}

+

{{ ice_cream.title }}

+
+
+

Описание

+

{{ ice_cream.description }}

+
+
+ +
+
{% endblock %} - \ No newline at end of file diff --git a/anfisa_for_friends/templates/ice_cream/list.html b/anfisa_for_friends/templates/ice_cream/list.html index 65f098c2..17701bed 100644 --- a/anfisa_for_friends/templates/ice_cream/list.html +++ b/anfisa_for_friends/templates/ice_cream/list.html @@ -1,19 +1,33 @@ {% extends "base.html" %} +{% load static %} {% block title %} Анфиса для друзей. Каталог мороженого {% endblock %} {% block content %} -

Каталог мороженого

-
-{% endblock %} \ No newline at end of file +

Каталог мороженого

+
+ {% for ice_cream in ice_cream_list %} +
+
+ + +
+
{{ ice_cream.title }}
+

+ {{ ice_cream.description|truncatewords:10 }} +

+ + Подробнее --> + +
+
+
+ {% endfor %} +
+{% endblock %} diff --git a/anfisa_for_friends/templates/includes/footer.html b/anfisa_for_friends/templates/includes/footer.html index 2d3af22c..ef9f1777 100644 --- a/anfisa_for_friends/templates/includes/footer.html +++ b/anfisa_for_friends/templates/includes/footer.html @@ -1,3 +1,3 @@ -
-

Копирайт, год создания

-
\ No newline at end of file +
+

© 2022 «MyKit Corp»

+
\ No newline at end of file diff --git a/anfisa_for_friends/templates/includes/header.html b/anfisa_for_friends/templates/includes/header.html index 66520481..9c3a5a75 100644 --- a/anfisa_for_friends/templates/includes/header.html +++ b/anfisa_for_friends/templates/includes/header.html @@ -1,17 +1,63 @@ {% load static %} +{% with request.resolver_match.view_name as view_name %}
- -
\ No newline at end of file + +{% endwith %} \ No newline at end of file From 2bfda6940e3ae0ae547efb6006f7c61d04a8c6ae Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 06:37:13 +0000 Subject: [PATCH 2/2] feat: Add statistic and users apps This commit introduces two new features: 1. A 'statistic' app with '/statistic/google' and '/statistic/yandex' routes. 2. A 'users' app that implements a custom email-based authentication system. The 'users' app includes: - A CustomUser model with email as the username field. - A CustomUserManager to handle user creation. - Forms, views, and templates for signup, login, and logout. - Updated project settings and URL configurations. --- .../anfisa_for_friends/settings.py | 8 ++++ anfisa_for_friends/anfisa_for_friends/urls.py | 2 + anfisa_for_friends/statistic/__init__.py | 0 anfisa_for_friends/statistic/admin.py | 3 ++ anfisa_for_friends/statistic/apps.py | 6 +++ .../statistic/migrations/__init__.py | 0 anfisa_for_friends/statistic/models.py | 3 ++ anfisa_for_friends/statistic/tests.py | 3 ++ anfisa_for_friends/statistic/urls.py | 10 ++++ anfisa_for_friends/statistic/views.py | 9 ++++ anfisa_for_friends/templates/users/login.html | 14 ++++++ .../templates/users/signup.html | 14 ++++++ anfisa_for_friends/users/__init__.py | 0 anfisa_for_friends/users/admin.py | 3 ++ anfisa_for_friends/users/apps.py | 6 +++ anfisa_for_friends/users/forms.py | 8 ++++ .../users/migrations/0001_initial.py | 42 ++++++++++++++++ .../0002_alter_customuser_managers.py | 18 +++++++ .../users/migrations/__init__.py | 0 anfisa_for_friends/users/models.py | 48 +++++++++++++++++++ anfisa_for_friends/users/tests.py | 3 ++ anfisa_for_friends/users/urls.py | 10 ++++ anfisa_for_friends/users/views.py | 21 ++++++++ 23 files changed, 231 insertions(+) create mode 100644 anfisa_for_friends/statistic/__init__.py create mode 100644 anfisa_for_friends/statistic/admin.py create mode 100644 anfisa_for_friends/statistic/apps.py create mode 100644 anfisa_for_friends/statistic/migrations/__init__.py create mode 100644 anfisa_for_friends/statistic/models.py create mode 100644 anfisa_for_friends/statistic/tests.py create mode 100644 anfisa_for_friends/statistic/urls.py create mode 100644 anfisa_for_friends/statistic/views.py create mode 100644 anfisa_for_friends/templates/users/login.html create mode 100644 anfisa_for_friends/templates/users/signup.html create mode 100644 anfisa_for_friends/users/__init__.py create mode 100644 anfisa_for_friends/users/admin.py create mode 100644 anfisa_for_friends/users/apps.py create mode 100644 anfisa_for_friends/users/forms.py create mode 100644 anfisa_for_friends/users/migrations/0001_initial.py create mode 100644 anfisa_for_friends/users/migrations/0002_alter_customuser_managers.py create mode 100644 anfisa_for_friends/users/migrations/__init__.py create mode 100644 anfisa_for_friends/users/models.py create mode 100644 anfisa_for_friends/users/tests.py create mode 100644 anfisa_for_friends/users/urls.py create mode 100644 anfisa_for_friends/users/views.py diff --git a/anfisa_for_friends/anfisa_for_friends/settings.py b/anfisa_for_friends/anfisa_for_friends/settings.py index a8c9efe0..ca1b7d6a 100644 --- a/anfisa_for_friends/anfisa_for_friends/settings.py +++ b/anfisa_for_friends/anfisa_for_friends/settings.py @@ -9,6 +9,8 @@ ALLOWED_HOSTS = [] INSTALLED_APPS = [ + 'users.apps.UsersConfig', + 'statistic.apps.StatisticConfig', 'homepage.apps.HomepageConfig', 'ice_cream.apps.IceCreamConfig', 'about.apps.AboutConfig', @@ -94,3 +96,9 @@ ] DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +AUTH_USER_MODEL = 'users.CustomUser' + +LOGIN_URL = 'users:login' +LOGOUT_URL = 'users:logout' +LOGIN_REDIRECT_URL = 'homepage:index' diff --git a/anfisa_for_friends/anfisa_for_friends/urls.py b/anfisa_for_friends/anfisa_for_friends/urls.py index 08c8ba7e..21867092 100644 --- a/anfisa_for_friends/anfisa_for_friends/urls.py +++ b/anfisa_for_friends/anfisa_for_friends/urls.py @@ -5,5 +5,7 @@ path('', include('homepage.urls', namespace='homepage')), path('about/', include('about.urls', namespace='about')), path('ice_cream/', include('ice_cream.urls', namespace='ice_cream')), + path('statistic/', include('statistic.urls', namespace='statistic')), + path('auth/', include('users.urls', namespace='users')), path('admin/', admin.site.urls), ] diff --git a/anfisa_for_friends/statistic/__init__.py b/anfisa_for_friends/statistic/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/anfisa_for_friends/statistic/admin.py b/anfisa_for_friends/statistic/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/anfisa_for_friends/statistic/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/anfisa_for_friends/statistic/apps.py b/anfisa_for_friends/statistic/apps.py new file mode 100644 index 00000000..a38a6cc0 --- /dev/null +++ b/anfisa_for_friends/statistic/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class StatisticConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'statistic' diff --git a/anfisa_for_friends/statistic/migrations/__init__.py b/anfisa_for_friends/statistic/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/anfisa_for_friends/statistic/models.py b/anfisa_for_friends/statistic/models.py new file mode 100644 index 00000000..71a83623 --- /dev/null +++ b/anfisa_for_friends/statistic/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/anfisa_for_friends/statistic/tests.py b/anfisa_for_friends/statistic/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/anfisa_for_friends/statistic/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/anfisa_for_friends/statistic/urls.py b/anfisa_for_friends/statistic/urls.py new file mode 100644 index 00000000..02f2f6ae --- /dev/null +++ b/anfisa_for_friends/statistic/urls.py @@ -0,0 +1,10 @@ +from django.urls import path + +from . import views + +app_name = 'statistic' + +urlpatterns = [ + path('google/', views.google_search, name='google_search'), + path('yandex/', views.yandex_search, name='yandex_search'), +] diff --git a/anfisa_for_friends/statistic/views.py b/anfisa_for_friends/statistic/views.py new file mode 100644 index 00000000..2cb68c6e --- /dev/null +++ b/anfisa_for_friends/statistic/views.py @@ -0,0 +1,9 @@ +from django.http import HttpResponse + + +def google_search(request): + return HttpResponse('Это станица для поисковой системы Google') + + +def yandex_search(request): + return HttpResponse('Это станица для поисковой системы Yandex') diff --git a/anfisa_for_friends/templates/users/login.html b/anfisa_for_friends/templates/users/login.html new file mode 100644 index 00000000..b72cb73c --- /dev/null +++ b/anfisa_for_friends/templates/users/login.html @@ -0,0 +1,14 @@ +{% extends "base.html" %} + +{% block title %} + Login +{% endblock %} + +{% block content %} +

Login

+
+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} diff --git a/anfisa_for_friends/templates/users/signup.html b/anfisa_for_friends/templates/users/signup.html new file mode 100644 index 00000000..87cfda74 --- /dev/null +++ b/anfisa_for_friends/templates/users/signup.html @@ -0,0 +1,14 @@ +{% extends "base.html" %} + +{% block title %} + Sign Up +{% endblock %} + +{% block content %} +

Sign Up

+
+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} diff --git a/anfisa_for_friends/users/__init__.py b/anfisa_for_friends/users/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/anfisa_for_friends/users/admin.py b/anfisa_for_friends/users/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/anfisa_for_friends/users/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/anfisa_for_friends/users/apps.py b/anfisa_for_friends/users/apps.py new file mode 100644 index 00000000..72b14010 --- /dev/null +++ b/anfisa_for_friends/users/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class UsersConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'users' diff --git a/anfisa_for_friends/users/forms.py b/anfisa_for_friends/users/forms.py new file mode 100644 index 00000000..1497be95 --- /dev/null +++ b/anfisa_for_friends/users/forms.py @@ -0,0 +1,8 @@ +from django.contrib.auth.forms import UserCreationForm +from .models import CustomUser + + +class CustomUserCreationForm(UserCreationForm): + class Meta(UserCreationForm.Meta): + model = CustomUser + fields = ('email',) diff --git a/anfisa_for_friends/users/migrations/0001_initial.py b/anfisa_for_friends/users/migrations/0001_initial.py new file mode 100644 index 00000000..de8b109a --- /dev/null +++ b/anfisa_for_friends/users/migrations/0001_initial.py @@ -0,0 +1,42 @@ +# Generated by Django 3.2.16 on 2025-09-04 06:17 + +import django.contrib.auth.models +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='CustomUser', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('email', models.EmailField(max_length=254, unique=True, verbose_name='email address')), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), + ], + options={ + 'verbose_name': 'user', + 'verbose_name_plural': 'users', + 'abstract': False, + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + ] diff --git a/anfisa_for_friends/users/migrations/0002_alter_customuser_managers.py b/anfisa_for_friends/users/migrations/0002_alter_customuser_managers.py new file mode 100644 index 00000000..d02af45e --- /dev/null +++ b/anfisa_for_friends/users/migrations/0002_alter_customuser_managers.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.16 on 2025-09-04 06:34 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0001_initial'), + ] + + operations = [ + migrations.AlterModelManagers( + name='customuser', + managers=[ + ], + ), + ] diff --git a/anfisa_for_friends/users/migrations/__init__.py b/anfisa_for_friends/users/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/anfisa_for_friends/users/models.py b/anfisa_for_friends/users/models.py new file mode 100644 index 00000000..dd970979 --- /dev/null +++ b/anfisa_for_friends/users/models.py @@ -0,0 +1,48 @@ +from django.contrib.auth.models import AbstractUser, BaseUserManager +from django.db import models +from django.utils.translation import gettext_lazy as _ + + +class CustomUserManager(BaseUserManager): + """ + Custom user model manager where email is the unique identifiers + for authentication instead of usernames. + """ + def create_user(self, email, password, **extra_fields): + """ + Create and save a User with the given email and password. + """ + if not email: + raise ValueError(_('The Email must be set')) + email = self.normalize_email(email) + user = self.model(email=email, **extra_fields) + user.set_password(password) + user.save() + return user + + def create_superuser(self, email, password, **extra_fields): + """ + Create and save a SuperUser with the given email and password. + """ + extra_fields.setdefault('is_staff', True) + extra_fields.setdefault('is_superuser', True) + extra_fields.setdefault('is_active', True) + + if extra_fields.get('is_staff') is not True: + raise ValueError(_('Superuser must have is_staff=True.')) + if extra_fields.get('is_superuser') is not True: + raise ValueError(_('Superuser must have is_superuser=True.')) + return self.create_user(email, password, **extra_fields) + + +class CustomUser(AbstractUser): + username = None + email = models.EmailField(_('email address'), unique=True) + + USERNAME_FIELD = 'email' + REQUIRED_FIELDS = [] + + objects = CustomUserManager() + + def __str__(self): + return self.email diff --git a/anfisa_for_friends/users/tests.py b/anfisa_for_friends/users/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/anfisa_for_friends/users/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/anfisa_for_friends/users/urls.py b/anfisa_for_friends/users/urls.py new file mode 100644 index 00000000..c4242ec9 --- /dev/null +++ b/anfisa_for_friends/users/urls.py @@ -0,0 +1,10 @@ +from django.urls import path +from . import views + +app_name = 'users' + +urlpatterns = [ + path('signup/', views.SignUpView.as_view(), name='signup'), + path('login/', views.CustomLoginView.as_view(), name='login'), + path('logout/', views.CustomLogoutView.as_view(), name='logout'), +] diff --git a/anfisa_for_friends/users/views.py b/anfisa_for_friends/users/views.py new file mode 100644 index 00000000..e5e1c64f --- /dev/null +++ b/anfisa_for_friends/users/views.py @@ -0,0 +1,21 @@ +from django.views.generic.edit import CreateView +from django.contrib.auth.views import LoginView, LogoutView +from django.urls import reverse_lazy + +from django.contrib.auth.forms import AuthenticationForm +from .forms import CustomUserCreationForm + + +class SignUpView(CreateView): + form_class = CustomUserCreationForm + success_url = reverse_lazy('homepage:index') + template_name = 'users/signup.html' + + +class CustomLoginView(LoginView): + form_class = AuthenticationForm + template_name = 'users/login.html' + + +class CustomLogoutView(LogoutView): + next_page = reverse_lazy('homepage:index')