From 1219966c84851a1870db72244eb9b6a3b74d2f0c Mon Sep 17 00:00:00 2001 From: NikDizell Date: Mon, 8 Dec 2025 15:31:10 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=B1=D1=80=D0=B0=D0=BB=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=80=D0=B8=D0=B8=20=D1=81?= =?UTF-8?q?=D0=BB=D0=B8=D1=8F=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 7 +- .../__pycache__/settings.cpython-310.pyc | Bin 3845 -> 0 bytes .../__pycache__/urls.cpython-310.pyc | Bin 1278 -> 0 bytes .../__pycache__/wsgi.cpython-310.pyc | Bin 582 -> 0 bytes .../__pycache__/admin.cpython-310.pyc | Bin 5647 -> 0 bytes .../__pycache__/apps.cpython-310.pyc | Bin 503 -> 0 bytes .../context_processors.cpython-310.pyc | Bin 606 -> 0 bytes .../__pycache__/forms.cpython-310.pyc | Bin 1115 -> 0 bytes .../__pycache__/middleware.cpython-310.pyc | Bin 1903 -> 0 bytes .../__pycache__/models.cpython-310.pyc | Bin 8396 -> 0 bytes .../__pycache__/sitemaps.cpython-310.pyc | Bin 2399 -> 0 bytes .../__pycache__/urls.cpython-310.pyc | Bin 1067 -> 0 bytes .../__pycache__/views.cpython-310.pyc | Bin 9032 -> 0 bytes .../__pycache__/0001_initial.cpython-310.pyc | Bin 947 -> 0 bytes ...ompetence_content_and_more.cpython-310.pyc | Bin 1368 -> 0 bytes ...ed_competence_is_published.cpython-310.pyc | Bin 1423 -> 0 bytes ...4_rename_photo_recall_scan.cpython-310.pyc | Bin 613 -> 0 bytes .../0005_auto_20231124_1519.cpython-310.pyc | Bin 1259 -> 0 bytes .../0006_alter_recall_scan.cpython-310.pyc | Bin 659 -> 0 bytes .../__pycache__/0007_solution.cpython-310.pyc | Bin 1284 -> 0 bytes .../__pycache__/0008_home.cpython-310.pyc | Bin 1260 -> 0 bytes ...t_alter_competence_options.cpython-310.pyc | Bin 1433 -> 0 bytes ...backrequest_email_and_more.cpython-310.pyc | Bin 834 -> 0 bytes .../0011_visitor_pageview.cpython-310.pyc | Bin 1365 -> 0 bytes ...12_callbackrequest_is_read.cpython-310.pyc | Bin 668 -> 0 bytes ...krequest_notification_sent.cpython-310.pyc | Bin 720 -> 0 bytes .../programmer_tags.cpython-310.pyc | Bin 751 -> 0 bytes .../__pycache__/seo_tags.cpython-310.pyc | Bin 950 -> 0 bytes .../email_notifications.cpython-310.pyc | Bin 1977 -> 0 bytes programmer/admin.py | 172 ------ programmer/apps.py | 10 - programmer/context_processors.py | 14 - programmer/forms.py | 35 -- programmer/middleware.py | 56 -- programmer/models.py | 157 ----- programmer/sitemaps.py | 66 --- programmer/templates/admin/base.html | 81 --- programmer/templates/admin/base_site.html | 28 - .../templates/admin/callback_stats.html | 47 -- programmer/templates/admin/statistics.html | 133 ----- .../emails/callback_notification.html | 59 -- .../templates/emails/daily_summary.html | 62 -- programmer/templates/programmer/about.html | 156 ----- programmer/templates/programmer/base.html | 557 ------------------ programmer/templates/programmer/callback.html | 10 - .../templates/programmer/competence.html | 74 --- programmer/templates/programmer/humans.txt | 15 - programmer/templates/programmer/index.html | 105 ---- programmer/templates/programmer/recall.html | 151 ----- programmer/templates/programmer/robots.txt | 20 - programmer/templates/programmer/sitemap.xml | 14 - programmer/templates/programmer/solution.html | 72 --- programmer/templatetags/programmer_tags.py | 17 - programmer/tests.py | 6 - programmer/urls.py | 29 - programmer/views.py | 256 -------- 56 files changed, 6 insertions(+), 2403 deletions(-) delete mode 100644 OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc delete mode 100644 OneCprogsite/OneCprogsite/__pycache__/urls.cpython-310.pyc delete mode 100644 OneCprogsite/OneCprogsite/__pycache__/wsgi.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/__pycache__/admin.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/__pycache__/apps.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/__pycache__/context_processors.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/__pycache__/forms.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/__pycache__/middleware.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/__pycache__/models.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/__pycache__/sitemaps.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/__pycache__/views.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0001_initial.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0002_alter_competence_options_alter_competence_content_and_more.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0003_recall_rename_is_publiched_competence_is_published.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0004_rename_photo_recall_scan.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0005_auto_20231124_1519.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0006_alter_recall_scan.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0007_solution.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0008_home.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0009_callbackrequest_alter_competence_options.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0010_alter_callbackrequest_email_and_more.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0011_visitor_pageview.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0012_callbackrequest_is_read.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/migrations/__pycache__/0013_callbackrequest_notification_sent.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/templatetags/__pycache__/programmer_tags.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/templatetags/__pycache__/seo_tags.cpython-310.pyc delete mode 100644 OneCprogsite/programmer/utils/__pycache__/email_notifications.cpython-310.pyc diff --git a/.gitignore b/.gitignore index 161feaf..1e69eed 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,9 @@ ENV/ # OS .DS_Store -Thumbs.db \ No newline at end of file +Thumbs.db + +# Project specific +*.log +*.pot +*.py[co] \ No newline at end of file diff --git a/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc b/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc deleted file mode 100644 index e572069c45e474f8c912ef63d0e8a5f6cf63d3f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3845 zcmb7HTXWmS6$U`?BI@Fce80qSY+0skfuqz;+)UyMA|aV$-bSG87UL-f!mg;5a5EN^ zER6e<{EAKJ`@E338sKVB)Os~L7Q`Po@~mZfMuNjL3~$uFYFcfie?GP<`l}C zWmM>k=5${`#h*oU2HFy|vuMhk+YnG0P5&sM=^rHX4B~TnGz<0I&ms}gnV)2kJd4hn z=g>KH9?hc*=pwp=E~6_y6^Lk_M_17`;Jb>hr}d4rzDdNsY|f)E%nRt2c@Z?YG%A;o zVqU@0-qm;4a0%UhFPYc-f_VddY2G}h-T~?t=&pGSEtm?rXWmAO=9eIU2TSknqWh=< z^9yNz2|a-RJ-lEpLb;#P9-`&<(z^;$-;3rFk_@3zwO7Dp<@%oO_XCCEI3|9dDmy`> zbbMS3qo7Yoj1}nYVJBA0^mRoQukU!cxj;Ng<04hwrhgcah$9-bYOz*pce-X*Xraq&Y?0+)B=IHccJt0-`&I^1KdffIOD>{nsI zY8-^bq1Cb0)#38-E>?C1uB*6&#!9erVwLS9*a(wIIk4RUrvJ}g5#Gsc^iO{J+7*$> zT|3@Q)<$k1KE=);!pn~%`jx%1^u&3yw|}s-@b&)6@{=dqNaA*72kDsY;yc*&(fzlI4+79zn>(hjxV3)Wak`QVs5E=(LXKl1Gy^jI35O z^2U&sk*a*U2^=yn@YPz{{0~+d?Wi@VUJ!hkVf|)87aL-h)kA|Zgo`+74rBx;jTlEL zE8H4JEhF{yDMq-&+26CBeaJ)g&+8CB+zENY(Tv>vOlZAhPpVxw6B7oV%L0Nrh+OLM zEXaNm3|67g8&F}v6akAl21`E*W)9_$46TgvfI9^?TQj;RdN^Ek{P8|7H7JxL|6B2` zU;(g$pxFLJWHWsnTM?!q*n%q(lPPw0q5^RKB1HT$_|U9>`>J~s?*{&;vEayZ1ba2~ z6Eysoy~^73@nDQ9YIwv-mPLFLTh>#q5m&7&CYL@kKpnGuWJwNKc}Xp~1f93SJFw=x z_&0FNTM0?u32!+J=i15NcX)u7ZQsE(4kD^7a-$ZNF%)_j0Ab%&j{wE+8#NmIw;6!t zk7S%<893FyGo{AS@$8a%h_??24I)4yFS!g^&aq{AoO8?F01nqtln0Y4xu^&YD@OP= zfNIQ2aQOW??gf84@>NeyG_R;vpQR^wD z^+wZ_olhb5O>9BVK$O5cv{Fd!PcHK*mx}QApr0It6$$%7FuUo5={IDDM4GKZDq z4-?GCka3E@crJOE$^29K{K1K#$;11`)F04M9+2%dlF*m#i6Qm z+S)KFlev`CPuT#I$a8>Uc1CY$ji$u|XYptz^FG-}B!Td+9<#Ff4A(f?$^7dB?@&2% zoNdLUuMZT@3-{QJR&O=hR?2TAb0l7c3noHGgM9$p58}hh16H&wc$Hd~Sq!Ke!t0Mo z0cAzrbIEqZF9!}<{NV&Z1)xX+_W-j(2#*&(HcM-oq4Qi|WkauR>OJeZ{uh?7>uXyZ zY*uSFJ1_NmYLLO^8f~KoBp^Tn8LZrD)ayoo&)8H?Z*`km zPdC`vm&Qhe3pE=xjVBzNs%t%s?`^Ov+E(wGHFkvcLTff)vIBWK+tk_{TiS+h)jD+@ z7HqV1%j`hLl)$@IW93Pk6?m^_g8DsJxyDssa_R?pFCadf9?`je?Cfx`-e~H^5CG2C z^>uBl*|R{2jhn|`v!!Y^4OW1+0rn4~ zTM&py;n6tWa(%PY8pf8*z+rizZ;nQJ3dj>jx4FnER|qS8H@tbC!v9JFji8c+()5gY zHYXS5TtO=3OLOw{Tuz#nL`f`3(r@y=<=^Dsz{n*`f5wwGv9mc?$HDz+or1-2)o zy&)m-H~33=<%z$*1LE3gML|M>M6plo>vPXNwt2VfS@7`Bz3fBXvcBq{#RtZ$=kUpo z&|oXFu#KJErcUJ88rSj~btBhcH?Px1)G)Z7H)$(s8QjR1PIYXvnx|gm*%oQw7I7!- zN$17^yhJ?g-PkwI$ceh7HCYy0q)Qw?EAaJj`;+t7f|*;-ZRd%U4=$lFyukW56$UYmznp4@Czo&8IkHBQU|_)1~Qcp8IoPj6om;wnxX3H6IOURt_q= zs_h80;d7C**mYydKdZgW`6vVf=b8F?!0`5c-}?sl!t(91Ar+jF6i_|EG-Ci4+^loF<5!MQs0SIcG`!&n?g zcV`u9V@!BZNf2-`tZ4bytP&oyEH%^lguN3o6VWi>6-d>f2Ph+Rw7R zaK_5|&hCq|m*vvy-JOH27d96%j~v}nv-WXkjs0}xK^jvvEg-E RcF*qAI=1_x(Y|B1oS%^Dh(Q1V diff --git a/OneCprogsite/OneCprogsite/__pycache__/wsgi.cpython-310.pyc b/OneCprogsite/OneCprogsite/__pycache__/wsgi.cpython-310.pyc deleted file mode 100644 index ebfdfae021542a6ca8b072e5da9c1329f88541f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 582 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 diff --git a/OneCprogsite/programmer/__pycache__/context_processors.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/context_processors.cpython-310.pyc deleted file mode 100644 index bb6b4c0ddc102149af46af2b18db7d592fa791fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 606 zcmZWm%}(1u5Z<5IF~P}!Bd6TJqC^}Jg$f~}6p2d3iPW5;NKxcnQq$N=XV*Zu(#PNh zxbZx`_QWf2sF-m;Aa$hu=9`__`CHR$HW=m9ZNZ85iv-#fxMWj4*GYYt$ScVVb8;_U&e!l`)Tr5H5q`p(1{zXi)lVHsBG%= zxS#9ZC74-d5P@lyX&5IaclyRn@G8;P8nB(qMcJZ`-|sxEWT}CG18wWS)+wNBeI1Eo zjw`OjovfHtwL7W2dx69FaoOzk<6*ZqoSd9>zkR=LrS3Sl8q}ir)q&#OJvi;hC%0=` zpWB-Udpl8kckf_(cV~NlKN7HtRUkx&L|LC{H+2qxdH|n*7PEvEWMxP*P7^mt^K(N! zOHmEc;Ql{oA&n!y^sZ8UZL3w6tIO4O@ZI?`Ee&0Te#l)_sR{&#nNh`DAJH#XzZbHQ H2Qri|!KjA4 diff --git a/OneCprogsite/programmer/__pycache__/forms.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/forms.cpython-310.pyc deleted file mode 100644 index 8fdc0862e0c5c66420b8115ab9372f42e9c71ea6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1115 zcmZuw&1(}u6rb6zY`*%X236I%=?^qzc;^~3CraIfw8?l(TWU0zM(TZ zAV#KPMl}$OFzSKm$bTIvA+ z{8z_5t?Z$mye;^&#o@~ps$yE^V*bk}eS zti;M}jE!erkxf8vlfB8&-fD9^_Ml;-;{{xq-Q}T2^6SO1hgBMf@w3?k;wV^44|xrHci<&hi!&LG`DtPco^>QEk~>+&#tf%sqKpdvrX zzWfO3?R2wNs~zLzsOkc5kSKysh6q=q#KNL)u;XM5%{{pf+xOEgsCbZE!O(jQ$j|8p z0>}gS_0ydS^l=EaH)KCKhpV#V|I^8QwWMsmHza^020^M@IMohcKN z+*j68i~B4R8piTZ;ph*MVO6+~^bc(t!^nurt+rT`$C0vpZ;|`aJ0dQ^#!UQ}y?495 zuolDDJ5la}2;007*IC=^G(%8PE9Uh_9X`_)VKZ~k5MB^)QP18%t-GcSybs7zbOVG< z3~EzD)2K%6--dCPhRiSPyLKLP8ZG=3mto_4)ev}5!~}{-6d3;7@zBC|Buo%E@tFhS v6wM;@RZCgJ=7$7X8EMgw!TcODh>t5`yZF2#JX493=mq@`?E_C_ diff --git a/OneCprogsite/programmer/__pycache__/middleware.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/middleware.cpython-310.pyc deleted file mode 100644 index 9fc794eb4083d9587c0f5159bf2f878a26a59948..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1903 zcmZ`(-EJH;6t+FHGn2{Yr)eb$MJV(FX{4$FgoIQf)Tr5(3%ZFmp)E@!YqECI39~a> z+uLnd6NHrBRy+V8Z7z8l?tRNuk$8a$70&VOwn+&d+4K3>$38#bak;P%6KKDem$Hiy zA%EcHbn{?x6S}?ugCK(Dq))rF&$^5f!GxE4eZT8F?B|Vs&W2%m!nk49-cRAh_T;- zt}!$ftq2FtL7TS0vgUy_TuD7B3oXGPU(0-7LFmYDM4`gVuQzV&Zap;*%VPTDTdF*i zJ+mtg)8e3nANVbIHw$@dpvnU`L7>upU#i{yYs;<=p4y1>tjG-KAzFl{#dLh-zg}FQ z?K|TRrVqPw=VJgBJtPw<=n2&qrkFWQCaeM}B^8-?h>lprz-g~Nj@GnEP1ai*hij?m zXT@6LTYr$6hc<>4W%MWmyaYMxea{DwU;Y>p?1GYbY7VZop^}e=QX3o1V&{TY5A(PK z9POof&N&8AV?Zynn8wWiKX>chXWR`y3)P*wF9D4A47htje%hwQutV?A2d5k0Vt_6J z4kr;Z=LDR0*h4J*=fLRMt|MmVKr^nGnV&RINIi}>IGwp$&(ey7#mvBWl=sMEUL>a;qL zMsKKc8)pNa3IUnXHXdrJIOMP}n6!PVqyn1H?`KLI$Sbhb#(6r!2~+PtoNXlJemcyJ zR#@lb_gYGoYSl3!D-KqX6st&z8>`8R!Zg_+HDy2RDWtRw%RQ_RZG)bYsgY^{r3+YV zy*vY3cs8*9-PX>!^+2eQ)Ae$x_*A8VGOs8{>I$NHXDjcOL-54c>0@c z@ZKdyUgd4icKA@oZk{yS-AgX_5BTlP&i(byMr#AnOL|S=`F6h3y1Tj4;_Dk59jMw5 zL8h+aLPHPo%q0GsP<5A{@cmN3<0+&-q!QeXmG`Eg)hbN!$;?XflvHYRyeWV$TuSDW7+njlQVO{Sr&Ty=2Sa Jf0M3w{{kNP)u{jg diff --git a/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc deleted file mode 100644 index 90f1ff95790f252f89b80085d98133da14971525..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8396 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 diff --git a/OneCprogsite/programmer/__pycache__/sitemaps.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/sitemaps.cpython-310.pyc deleted file mode 100644 index 46831acb90b210331d2a3bc99a035f7fb4c434be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2399 zcmb_d&5zqe6rZsj+ew`LV7qKvzDoHFi0~;PAw(-J5{N^n25hE?{^iTv_@9?#5szxU?7tkI}39FHDe zihs2k`<=k@s35qBPyQnc!30lO%6-mBHxeT?eG_$4Sc#QZ{7P#3cIx;}>iRBcUocS- z_5&tt$?uzf6|o~+#ID9Q#8pv4T+_IYxGp@zp2i;HhS);9rEx=6WnFr*A+{e{{+8J3 zu;%Uw+Qph&Ii0wWX*imp3i5jixjf-CWhv{+ES1XbWXZUQv!SXTX6Z;4au`Wve1c^C+8;&b{c3dwvfm~RN~o5Jud^7jGrD|7FBTR3Qmt9Cm@Sj5roSl%s-`4bo8 z`1^)((rj4tlSxE2Ee7dy&>=p#i=u}F|H5%Iqus11t50@U!frM$l$$TicfxL*#KlC} zplzQq^x4W~atwR8hZg^Q_4y}9wa zQx>f~vmKtLmu`|p$YwV55W!^>)2r*JEp3O3*a%r{~DK!lm?Z!yKaI1fhSZW8BxDViqWePznY zx)j!2*~f8GNPtWDcF7Oz0y#*o>G*B&>F$zM=R}TjQ=3Dl+~Wh*VQ>Xi%(Z$EBhBNH z2n#tYV`!ooPn@cpB+Ls81eu^uw)u2#`Q&oGJ#*lB{03ei@gj+9Bwiw+WAiR){}-F< zII&HWFOwj&F(TWGI#5OhUcptpN59ed>&CfZ0V)LW8VY3IA^i;!Z<08V@@q8NL^0ie z;?NDG!&|hH=!UmRyhGy5e;rfegiMF`P~eR$%R}i^Yr!qNzq(fMqBr;eCp7JvJ3>aEf`;_?8ylVcgtRJzN!4J`q*U1^pAfb&6 zHs<|ig}q}v{Zhv+A&8(4Sv~tcGA?(q1u6w6n zU9`CzEA-gDVhk{m30V`KS|2&jn7Z>>%~ z%^}rwT{3`jA1Hi4)?lk$?5Z!znV@T<+)wAdE diff --git a/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc deleted file mode 100644 index b007e842529a6f4f21a330029c569844d1b4b65e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1067 zcmZvaOK;Oa5PII%@ zK$SG1MI7Q@RgpbdBCV2_piSB(cc4SMB`-sltdzV8%Ve$O9;}e{k~d(LY?izQF1Z6< zVv@UPu`tRutdVAZj?#3X>^bBsQzqnK zH_7CVrZ6FU156t+Z)(p`6o0~NZ!qr`r45SI1!j*iorRLSW&ZvJO}TzE`D1bxWn<>Y zER#GL`K5#Kza(%jZq(f2Y{aDS<%JCFIb*#o!r~c)Oop5>`M$rUmj1ntS1^WhOXG~E zg5&!%xOLl%p-*{DThAI)c5PsR4vH}TyXvPd0UH) z7G1s76cctH>Ncv*P47YupJ#xU_M%~-4ynrGLo8mom=?Yo2|N?3wtw*A<7?G?cd-BF zdHC`8t#amge0X^B&ESu8KrMd1+TR%-UCIf|$|XGF>mDgO^jz#)YDR wN0b5|7R{Jms>Uv5WR}97ewD&U;Tav%!_g?DXKB7QDizcE<5jGmc4q_WFWGTGHUIzs diff --git a/OneCprogsite/programmer/__pycache__/views.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/views.cpython-310.pyc deleted file mode 100644 index 3c4cca78fb80a8e3a6be559879c718e17d4cd2f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9032 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 diff --git a/OneCprogsite/programmer/migrations/__pycache__/0001_initial.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0001_initial.cpython-310.pyc deleted file mode 100644 index 09854a6a8c1d625bfae6ac45e0eb6bc859e142e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 947 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 S3*M?Ff7><3nR6G&lK(Fa)}ZzP diff --git a/OneCprogsite/programmer/migrations/__pycache__/0006_alter_recall_scan.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0006_alter_recall_scan.cpython-310.pyc deleted file mode 100644 index caac6b8680e0b8b5179cd10a793c115d21cb4abb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 659 zcmYjP&1w`u5bmFu-PvIyB2k}Ug}v;bCZGg~D2fMTz>~v3)0ryQU1p}&o*5w?)ob3u zi_f6s8P;oGJ$dj21c}wNkxfBWcl}Ub)z@uyc49{I`T1rm|I;hOj)^3VF2?g^Qo)SCFhW| z8j(SkaA1i5KIe(VU>SM<>@2$wKnR^P0o^l6xdbc&F{|Fv#WewpK1={5HWHQ-P zx~YwtO=fqe)7d>W-J9Nb9gCUHa~D*ZE*$CbK#o>=5Rz)MXHS}D zpha*%p+Z99!bh*%0%}B+(sJM*@LuQ2sdo+t357RfSJ@ePJU`F-{JnWjhr^yj9zIs^|!f@1uCv^Dx~E3 zR3tjMp32hjqFDr6mo@uvbL8uRD2tR&6^a5u_cIm6LhbPzxTm{0sz}J_HtNC0sJ7D_ zc_L!ets*KUK0PM#%G0z|KU4?R!|M0yuzFlQseUE&nDC*khPcHgCSkFwh9s){fcaEK znF*v^Hp)L%e^d|WpDif0wxvjJ)bdMFoJou^DQr#4RikpBJRMYz$j5Kh!TbwSzo$D> zndVUv))L>*`BC*~{`LGz8x=*P`$ZIElWKX!*!h;U?^Flp$omsA^`MSnevbmLc}dbw zxBzHExB6uUL{)iqQQrnqr*9~raL7VnnI#Lg_8`i6R&L8E-$f|bn#|{St6yv)N6&~O z%?{v>C}m+4OLJMPpXQ&Ez+rVXzcc@8`^zAaaKCqfCi z?xdFW{OV|^18z&nx$bdJT~bP<{ebhErI1F;AixY0z+@U>t{8=(`y2M6Trq8>Jo9C6 zDGJ}GD|FfT(A|w)p_=U$-YV+taFZC@BJyiExRj<6MN*?)nqkwgKRfD8vT2up$D0=> z*Y=9tG-+P^no4IlEhaD%Ntn_rj|!Z8l;DQB{T7_G!Q|vOFrkKchv&`hKcDR>^Mh&A zlfOYr;4sfW_FK$dWy|j3WdE=}bK9=}pZ|AoY_+aZ%XI4i&cn7P#qwYePol4PZ;^E! Ryj#=zo@*Q$&&zDh`yZl3ys-cP diff --git a/OneCprogsite/programmer/migrations/__pycache__/0008_home.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0008_home.cpython-310.pyc deleted file mode 100644 index 20cebcbb72c97bebfdd7762d7a1be5517036ff12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1260 zcmYjR&yU+g6t>4s;v`Plvdhv^puH?oq|)6R2q7rlRiTHLO019?MHzq+uNJ=A;Ea&IUB0b?EOC z2=H3~ZRkMvkRT2bw^5=8r!0OBaR*l5G(2zdD&j7lufYozug~#|aK_@Zh(kPo3C+n-9_e8;I#!$ae#%02v zo*+Nf8C=x&YO0>7Khz_2q>j}uh>j3HvV^lcG~roPj-?@1w?-l>c~(}TQT%asPfcg{ zW?#=9pm1X^VcG3kt~16+DFzeqyK9U6=EkkfjdXJZHmkrGc&Lui#4#$jt2_}5Xenv~ z-7-c4bz;?7Bm1p!rKT5VUto}r)vtA!)^p85CO)GKU|GM)0g0*3E$d@ykLSsngr8Uo zf#ne`)Y@TO(7f79;$qC9S~u!Hs6S`-)z9j8)c@@nO&E9!_&%$W(kfQxjp#QhG({ed zFyaRoFEaG`Jle0+wC~kER+o!H^Q4k2(SeYFWy_+zr+r(k=6=i*D0EBY_Tt~@pV9%f zm84X6D8)Xg5{~@<7;T0hg&a%0n$oafGe{$qSv~QPxKi+w3c=Mnf zi){X)H>H^HQ8|PO%OZiVA};yx!;Ej6yKljw35JWNA7VSaNzHY-lpjd*D{10me4L9 zok5-U>d=5Dw8o5ZyTBcon&4@|4VZ!134Vrf6XsxkY?AZ|LM^hl0M8cM&k=5u^^)%3FC`)khd=6iT6!z5MAgVigFy}Q!0RoltZhz|uiDS~Rn!V4U+ z$#3GOY9uH;$M?2SwLd_y7A43-hYZ@99s*S^s}hl4%LnZ zxufbu0(7$3oRPbB(@!_Wmof)xK~n`kqxrGS|mjlooMnQ}zhC@`9)JuKL7Icu`P%sauvb&Vau6&q(s%!DTEV)MxPLo~{i#SEA z9xFVGGqk?en^tvRGzaIZ$vI73<|D1!oZreEUpI_KfH8(Z!FZSmMw+U%T(sU*J*L9a zJMGJ!dx@Iziq1qemNy(xE}L)bcA0Fi;_b9tc2=l$SLwJ**uES^K00BEW-s|Eio*K! zrxl4}oLmn-7~%rCEXZG5D{l;LY^Kz)lOMk!q7e?$0gRl`jp&znDGsiOxU2`Q07nxy zIJ$KPG<&b};biJWId$C8k?^DA;FBX-j5me8@AN1oi$v-Mv+O5!g_-kg#? zDsCa;gd2h+Mqnf~paywLIOXO6;U*Yk^PL%(+))mKLg$WE?~h zY1jGVqOyuqJVOQ~FgOV)H%3Naf;F}^0CdI++~PJ;hc8Sl?o4Jr7kv)eJ$`9IwS7bb zmv^y z7b2AnNf?WblfPJTbrV_rrT$TWtG_q<&71nD{)zXn`M6Xc*GJ9!X1_l4EoBcym~P=n z!d)gH9hIBPN-H5$cL(G!D}be80=|h6dQh!~5olBPs~7}VPFp7qv$~=&KOx44rTQxZ z9&6a^z32lG8;ow4){1sM;Sgv zT*BZ*3J>*GT4lbT!Ti$<`u#io*v$ x&#?YXr7lX&X&bqQJ8`E4E%Ra9dE0I4oOd&ou46{!tW0Nk-_Rf$tw*n#{{i%m15W?| diff --git a/OneCprogsite/programmer/migrations/__pycache__/0011_visitor_pageview.cpython-310.pyc b/OneCprogsite/programmer/migrations/__pycache__/0011_visitor_pageview.cpython-310.pyc deleted file mode 100644 index b08544342a46d2d5361eaa8cd79b2883faf0c309..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1365 zcmZuxOK;mo5aupPiJ~Oi@vEuZr& zT3G>@mTzOLyFL0Oyr8$d&m0Gxh=CJvUsq# zQ^(l7BgQJLFGzcjGQMB${j#?7$aZhRCp>8_qi?}(!r?0$pLVR1#Ng{X8{TA-@Mser z5T_4K=gke7mf4vuh}tYeZ3e^P!BEJwLM>vMrehhOYkWV)vJ#j{l?s`I$O?_7{Z5st zDzxDWPG1>*d^GS(PtL1C#2RIVV7fD{GO4e`IbNAgiCW22eMHl{Ks_!>6uHdMglZ-v zfX1>k-HFl^>cYAnFw+K{$az|sFqJp3>DF2i7xTROM16KlTjhY4SVj+5r3kTfD;~#B zAeKVGB^BG6C`_R=o((;4^)A`#o!Ut;Yfe{iA`^V4@Pl#ZI#qvB2udZ)Uc$ZTf9Ih7^IAh-GY<5cG7rmb;;8uftd2iE@{P0`-%+{m$bCcixxKel=OKkub; zF?>24KCSg{2U{i(HCsZMP*4M4o+7P#LcE{L)D~kUz!?%1d91M1+*Z{+tb6gs{xI6L zNbd)gyreF@vP77j*O*gZ;^UK-O$!>he?$#Dr79b-1yh+Ph4JT=N=p;i6h9U@8aFRK znBH+-VS>8Z>mS=@n9kvuTq2!QysR2!Sj=$w7ys_)p(V#o*W;t-qm!%ZtjL!iaiWVU z#?`2aOdmQCIQlWiL(5|=tOy;gE{74F;DhD>61gh5Z<4&?`$~&A;ph?BhBu9Go$%-zFobu(`RHSzlQmD&e#tR?pi?LfZRT$ z1sL#xl|1I9hy`ay3V5O2 z`PSS}+Ys<9T@ZS%*Y!1dP5W04NhZ1;??H&L(q z6rQ|^xFD$U6?(6I_2j`95Ol4ctYmQus=B_aqO0obRvQ~VM)LH}Ap6M~`|iPM2?=bG znyX}h0nb^%V_pPtz}Z6v0f;vY1oF9fEn)%T6EM8rLoqU~W>M zIxQUnTcl=023gF3#R2dcj|GPFmT!RVc?UvhLHi(p&Vis@1Q9jry6&TY9elfmR@AR3 zP`k^Uo7Zp1G|BTxl0MhCSEH$9W~9ah+`0b}?n0@mY?`Ibu+m^zZP(XmAp6#Su!r`e zUD_}9GkIU_Cwq9sE{|T>Z$~ffdrGguOB$d9I8Exja{U*mC(58KlLCi=i15od$b~-U zTGI@3*r637*~F!EJt?WK&XN4SlzVlO`&y3x7gz$8X@*7zG?&0kW0)u9OwnPo3dfI2yzj|uz?#+Z z`aQ?Q@69v(o?&sc*w_9GwMorIG7$?zcpSC@9`HU7e@DknerFiE?rMe+Oqvawy_)2D Yft5F)dt7vT#nm19waoY)=YxUx3$IGyM*si- diff --git a/OneCprogsite/programmer/templatetags/__pycache__/programmer_tags.cpython-310.pyc b/OneCprogsite/programmer/templatetags/__pycache__/programmer_tags.cpython-310.pyc deleted file mode 100644 index 220100487ff3280779a7c859f3120dc312fef166..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 751 zcmY*X&5qMB5cW8~E!jmB#5>(25hU z{tELZwaK+C#5B|)o^y#>HL|qE z#UJa|O6{UjZF>8I=@Ev#`TgPL)8+Zrep3CN%g?oau~~*~Zqb z(HY)yL9Z@cNO7;9rZROxCZ(i&I2BnXitRx{O@GKeB%VHUph*GGHRBmfKvVPP(~*mZ zr!_Hkai@gD3WkoosaLwtTbF8C)rNXDHZ^`0NrHN_kM4(dc8_;-P^t&HY`H^7-xOi z=sd$M_t9{|X-pE@rqo~-v&3p!ln6StXQb^2Co1s@x4H9;4_%3%3iC4YE zO2nhuRU#S0ff9(TQb9QAs-Q15=`oYBTu6$Ty@y*qN2ACXX-pVY#$-xoIGyj(VoPTWQzwI9Smco>%CY6X?I!ZGl4p${(ZH- z+c_Ai<1Aes-2=!X(Ni5B1!+ISLxxIpUZ!Gi09n6q41gd>1awxC8=*UfwE_NMq<8uv z6@bI&n$FjoF%)GDP1SN~m2S~H)TVF~16Sr`W@bK1F{ir-{?Dn#*_7g}*o@3j^+I`j zxQi**D}N$JZ!+NWTG=;^>;=_T>M48FY#D|g6M}* t3BW%d;(r%L@DNykS0_kHR>{()u>%*(0_006gmI^ diff --git a/OneCprogsite/programmer/utils/__pycache__/email_notifications.cpython-310.pyc b/OneCprogsite/programmer/utils/__pycache__/email_notifications.cpython-310.pyc deleted file mode 100644 index 12f89e7a7cd93b53e317698bd2d260c16b566020..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1977 zcmah~&2Jk;6rWkI*K5aiOe(@REO0;uDM;m3Aw*~#Q7LJv+Es-KT5UaJXTyG&*;$G$ zrz$Ptf+`N&fYMe%0&b;hL`a+PFRZV7<%GEOT%^K#v$hE*)}A+CZ{K?}@ArEfRw^X| z&!2xUy5%AvzvJZSlY`0I(4sa7Mi}*oPutYj+8V{V=H-07t*dd)%lk&#P-ERI_-5Nw zNKqhP~yUtp&d!#20d6aBQ7NjaleGCeOo%c=yZpo<;jzW9uIsHT67=8 z@Et}+WSe|Lu4_9~Ql^cF)V6bC0VT^lMFPrnmj70}s_ke}A8A+VPEO`w*ML^&!903R znm3EgxJ4;BPgtQzWNAc4IoO|rRvu}rz|3oKF`!prMetWee-r&uljuaw4?dt|2QG3r zudL0D^nZ2UBdolmU((TbHo8bJl6obM@H`eg$#>%`$#3J!$?fD$a&P=)vOB(FjjzIF zH@TY}CijzjFgi%~l3gn~v|w}ydxy!dR`N@78}#oa`?z(G+=l(+XS4(s55`|)DyWO^ z>??0^1N=U?@%4{Zavc`$poOD`z{dX?0yhxi@I{VEj$ZFLo_E3Nd}s%ubh~Z`avcUs zThjLgCNM2}A*gJHkpz&KQ*Fq)E4dvDZ}_T0i#0`o^^C)t9JS}xa=-Vosv?_SV?YlgXw&zANEn^_|RI}2BknPCzVBZ@I z-^e^44IIJ3{k;Mw6%Sf}f?R1X}V z3mvXNAb8Wt^4i+Q`NoRF_@0 zrk-!trsuH*|0w1_I^>q9f@oLzp5q3yE2I1;BA$bdhwrbP*gP|kTVXKi>@y<7Ol-1k zC+LOHVNN$U0)7$_)>9K42*-z;*o-B>Wm8?(f3OlQ^#|$Gs(Q@AI(nUR;5<4GLetAs z&uMglnvYDQmMc+%YB1NR4nORThYLl6R<#K5%PR4)&A13|<*`p8=Z>ZhZBF)q;#! z8Fmr+){46S;qlg%8(HvoEQuN!GL^<4jKxIFa{7I5O4HSPK1)4bvM8gdpqK~I8Xi-Q zCT4&+oFTLe3VaIG;t5oK5(Ne)9!IeVqE5xLI7Z-P;&~XQ^D4_2Tt-*SYJ`fKj_I2w z()i0LROu{<7AVx`(^>|zrA{dL64st94*bxii<3RceSojzOJ3-}cSg}KotwQFbTckK zHd#@S%xab5V*yD9q)v-HF4r=`nYN8gw(ab6h$w*(9XXpir8=PbrXRA{<8L9(q8f-A OEvuhNOPZN0zw!?x&w1Mb diff --git a/programmer/admin.py b/programmer/admin.py index b2a1f5c..5962719 100644 --- a/programmer/admin.py +++ b/programmer/admin.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD from django.contrib import admin from django.utils import timezone from django.utils.html import format_html @@ -168,174 +167,3 @@ admin.site.register(Competence, ProgrammerAdmin) admin.site.register(Recall, RecallAdmin) admin.site.register(Solution, SolutionAdmin) admin.site.register(Home, HomeAdmin) -======= -from django.contrib import admin -from django.utils import timezone -from django.utils.html import format_html -from django.urls import path -from django.shortcuts import render -from django.http import HttpResponseRedirect -from django.contrib import messages -from .models import * - - -class ProgrammerAdmin(admin.ModelAdmin): - list_display = ('id', 'title', 'time_create', 'photo', 'is_published') - list_display_links = ('id', 'title') - search_fields = ('title', 'content') - list_editable = ('is_published',) - list_filter = ('time_create', 'is_published') - - -class RecallAdmin(admin.ModelAdmin): - list_display = ('id', 'title', 'time_create', 'scan', 'is_published') - list_display_links = ('id', 'title') - search_fields = ('title', 'content') - list_editable = ('is_published',) - list_filter = ('time_create', 'is_published') - - -class SolutionAdmin(admin.ModelAdmin): - list_display = ('id', 'title', 'time_create', 'is_published') - list_display_links = ('id', 'title') - search_fields = ('title', 'description', 'implementation') - list_editable = ('is_published',) - list_filter = ('time_create', 'is_published') - - -class HomeAdmin(admin.ModelAdmin): - list_display = ('id', 'title', 'time_create', 'is_published') - list_display_links = ('id', 'title') - search_fields = ('title', 'content') - list_editable = ('is_published',) - list_filter = ('time_create', 'is_published') - - -@admin.register(CallbackRequest) -class CallbackAdmin(admin.ModelAdmin): - list_display = ('name', 'phone', 'email', 'time_create', 'is_processed', 'is_read', 'new_badge') - list_display_links = ('name', 'phone') - list_editable = ('is_processed', 'is_read') - list_filter = ('time_create', 'is_processed', 'is_read') - search_fields = ('name', 'phone', 'email') - readonly_fields = ('time_create',) - actions = ['mark_as_read', 'mark_as_unread', 'mark_as_processed'] - actions = ['mark_as_read', 'mark_as_unread', 'mark_as_processed', 'resend_notification'] - - def resend_notification(self, request, queryset): - from .utils.email_notifications import send_callback_notification - count = 0 - for callback in queryset: - success = send_callback_notification(callback) - if success: - count += 1 - self.message_user(request, f'Уведомления отправлены для {count} заявок') - - resend_notification.short_description = "Переотправить email уведомления" - - def new_badge(self, obj): - if not obj.is_read: - return format_html('🆕 НОВАЯ') - return "" - - new_badge.short_description = 'Статус' - - def get_queryset(self, request): - # Показываем количество непрочитанных в заголовке - unread_count = CallbackRequest.objects.filter(is_read=False).count() - if unread_count > 0: - self.message_user( - request, - f'У вас {unread_count} непрочитанных заявок!', - messages.WARNING - ) - return super().get_queryset(request) - - def mark_as_read(self, request, queryset): - updated = queryset.update(is_read=True) - self.message_user(request, f'{updated} заявок отмечены как прочитанные') - - mark_as_read.short_description = "Отметить как прочитанные" - - def mark_as_unread(self, request, queryset): - updated = queryset.update(is_read=False) - self.message_user(request, f'{updated} заявок отмечены как непрочитанные') - - mark_as_unread.short_description = "Отметить как непрочитанные" - - def mark_as_processed(self, request, queryset): - updated = queryset.update(is_processed=True) - self.message_user(request, f'{updated} заявок отмечены как обработанные') - - mark_as_processed.short_description = "Отметить как обработанные" - - # Добавляем кастомное представление для статистики - def get_urls(self): - urls = super().get_urls() - custom_urls = [ - path('callback-stats/', self.admin_site.admin_view(self.callback_stats), name='callback_stats'), - ] - return custom_urls + urls - - def callback_stats(self, request): - today = timezone.now().date() - week_ago = today - timezone.timedelta(days=7) - - stats = { - 'total': CallbackRequest.objects.count(), - 'today': CallbackRequest.objects.filter(time_create__date=today).count(), - 'week': CallbackRequest.objects.filter(time_create__date__gte=week_ago).count(), - 'unread': CallbackRequest.objects.filter(is_read=False).count(), - 'unprocessed': CallbackRequest.objects.filter(is_processed=False).count(), - } - - context = { - **self.admin_site.each_context(request), - 'title': 'Статистика заявок', - 'stats': stats, - } - return render(request, 'admin/callback_stats.html', context) - -class ProgrammerAdmin(admin.ModelAdmin): - list_display = ('id', 'title', 'time_create', 'photo', 'is_published') - list_display_links = ('id', 'title') - search_fields = ('title', 'content') - list_editable = ('is_published',) - list_filter = ('time_create', 'is_published') - -class RecallAdmin(admin.ModelAdmin): - list_display = ('id', 'title', 'time_create', 'scan', 'is_published') - list_display_links = ('id', 'title') - search_fields = ('title', 'content') - list_editable = ('is_published',) - list_filter = ('time_create', 'is_published') - -class SolutionAdmin(admin.ModelAdmin): - list_display = ('id', 'title', 'time_create', 'is_published') - list_display_links = ('id', 'title') - search_fields = ('title', 'description', 'implementation') - list_editable = ('is_published',) - list_filter = ('time_create', 'is_published') - -class HomeAdmin(admin.ModelAdmin): - list_display = ('id', 'title', 'time_create', 'is_published') - list_display_links = ('id', 'title') - search_fields = ('title', 'content') - list_editable = ('is_published',) - list_filter = ('time_create', 'is_published') - -@admin.register(PageView) -class PageViewAdmin(admin.ModelAdmin): - list_display = ['url', 'timestamp', 'ip_address'] - list_filter = ['timestamp', 'url'] - search_fields = ['url', 'ip_address'] - date_hierarchy = 'timestamp' - - def get_queryset(self, request): - return super().get_queryset(request).order_by('-timestamp') - -admin.site.register(Competence, ProgrammerAdmin) -admin.site.register(Recall, RecallAdmin) -admin.site.register(Solution, SolutionAdmin) -admin.site.register(Home, HomeAdmin) ->>>>>>> master diff --git a/programmer/apps.py b/programmer/apps.py index c2c4ad0..c8b6481 100644 --- a/programmer/apps.py +++ b/programmer/apps.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD from django.apps import AppConfig @@ -6,12 +5,3 @@ class ProgrammerConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'programmer' verbose_name = 'Программисты' -======= -from django.apps import AppConfig - - -class ProgrammerConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'programmer' - verbose_name = 'Программисты' ->>>>>>> master diff --git a/programmer/context_processors.py b/programmer/context_processors.py index 7261401..41a7d3c 100644 --- a/programmer/context_processors.py +++ b/programmer/context_processors.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD from .views import menu from django.conf import settings @@ -10,17 +9,4 @@ def contact_info(request): return { 'CONTACT_EMAIL': getattr(settings, 'CONTACT_EMAIL', 'it@nserdyuk.ru'), 'CONTACT_PHONE': getattr(settings, 'CONTACT_PHONE', '+7 (960) 469-40-88'), -======= -from .views import menu -from django.conf import settings - - -def menu_processor(request): - return {'menu': menu} - -def contact_info(request): - return { - 'CONTACT_EMAIL': getattr(settings, 'CONTACT_EMAIL', 'it@nserdyuk.ru'), - 'CONTACT_PHONE': getattr(settings, 'CONTACT_PHONE', '+7 (960) 469-40-88'), ->>>>>>> master } \ No newline at end of file diff --git a/programmer/forms.py b/programmer/forms.py index 9023bc1..9726b2c 100644 --- a/programmer/forms.py +++ b/programmer/forms.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD from django import forms from .models import CallbackRequest @@ -31,38 +30,4 @@ class CallbackForm(forms.ModelForm): 'phone': 'Телефон', 'email': 'Электронная почта', 'question': 'Ваш вопрос' -======= -from django import forms -from .models import CallbackRequest - - -class CallbackForm(forms.ModelForm): - class Meta: - model = CallbackRequest - fields = ['name', 'phone', 'email', 'question'] - widgets = { - 'name': forms.TextInput(attrs={ - 'class': 'form-input', - 'placeholder': 'Ваше имя' - }), - 'phone': forms.TextInput(attrs={ - 'class': 'form-input', - 'placeholder': '+7 (___) ___-__-__' - }), - 'email': forms.EmailInput(attrs={ - 'class': 'form-input', - 'placeholder': 'your@email.com' - }), - 'question': forms.Textarea(attrs={ - 'class': 'form-textarea', - 'placeholder': 'Опишите ваш вопрос или задачу...', - 'rows': 4 - }), - } - labels = { - 'name': 'Имя', - 'phone': 'Телефон', - 'email': 'Электронная почта', - 'question': 'Ваш вопрос' ->>>>>>> master } \ No newline at end of file diff --git a/programmer/middleware.py b/programmer/middleware.py index 98e272c..494461e 100644 --- a/programmer/middleware.py +++ b/programmer/middleware.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD from .models import PageView, Visitor from django.utils import timezone from django.db import transaction @@ -52,59 +51,4 @@ class PageViewMiddleware: ip = x_forwarded_for.split(',')[0] else: ip = request.META.get('REMOTE_ADDR') -======= -from .models import PageView, Visitor -from django.utils import timezone -from django.db import transaction - - -class PageViewMiddleware: - def __init__(self, get_response): - self.get_response = get_response - - def __call__(self, request): - # Игнорируем статические файлы и админку - if not request.path.startswith('/static/') and not request.path.startswith('/admin/'): - self.track_page_view(request) - - response = self.get_response(request) - return response - - def track_page_view(self, request): - try: - with transaction.atomic(): - # Сохраняем просмотр страницы - PageView.objects.create( - url=request.path, - ip_address=self.get_client_ip(request), - user_agent=request.META.get('HTTP_USER_AGENT', ''), - referer=request.META.get('HTTP_REFERER', '') - ) - - # Обновляем статистику посетителя - ip = self.get_client_ip(request) - visitor, created = Visitor.objects.get_or_create( - ip_address=ip, - defaults={ - 'first_visit': timezone.now(), - 'last_visit': timezone.now() - } - ) - - if not created: - visitor.last_visit = timezone.now() - visitor.visit_count += 1 - visitor.save() - - except Exception as e: - # Логируем ошибку, но не прерываем выполнение - print(f"Error tracking page view: {e}") - - def get_client_ip(self, request): - x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') - if x_forwarded_for: - ip = x_forwarded_for.split(',')[0] - else: - ip = request.META.get('REMOTE_ADDR') ->>>>>>> master return ip \ No newline at end of file diff --git a/programmer/models.py b/programmer/models.py index e07c9a6..b62f79b 100644 --- a/programmer/models.py +++ b/programmer/models.py @@ -1,159 +1,3 @@ -<<<<<<< HEAD -from django.db import models -from django.urls import reverse -from django.utils import timezone -from django.db.models.signals import post_save, post_delete -from django.dispatch import receiver -from django.core.cache import cache -from .utils.email_notifications import send_callback_notification - - -class Recall(models.Model): - title = models.CharField(max_length=255, verbose_name='Организация') - content = models.TextField(blank=True, verbose_name='Отзыв') - scan = models.ImageField(upload_to="scan/%Y/%m/%d/", verbose_name='Фото') - time_create = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания') - time_update = models.DateTimeField(auto_now=True, verbose_name='Дата изменения') - is_published = models.BooleanField(default=True, verbose_name='Опубликован') - - def __str__(self): - return self.title - - def get_absolute_url(self): - return reverse('post', kwargs={'post_id': self.pk}) - - class Meta: - verbose_name = 'Отзыв' - verbose_name_plural = 'Отзывы' - ordering = ['time_create', 'title'] - - -class Competence(models.Model): - title = models.CharField(max_length=255, verbose_name='Программист') - content = models.TextField(blank=True, verbose_name='Компетенция') - photo = models.ImageField(upload_to="photos/%Y/%m/%d/", verbose_name='Фото') - time_create = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания') - time_update = models.DateTimeField(auto_now=True, verbose_name='Дата изменения') - is_published = models.BooleanField(default=True, verbose_name='Опубликован') - - def __str__(self): - return self.title - - def get_absolute_url(self): - return reverse('post', kwargs={'post_id': self.pk}) - - class Meta: - verbose_name = 'Компетенция' - verbose_name_plural = 'Компетенции' - ordering = ['time_create', 'title'] - - -class Solution(models.Model): - title = models.CharField(max_length=255, verbose_name='Наименование') - description = models.TextField(blank=True, verbose_name='Описание') - implementation = models.TextField(blank=True, verbose_name='Реализация') - closing = models.TextField(blank=True, verbose_name='Заключение') - time_create = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания') - time_update = models.DateTimeField(auto_now=True, verbose_name='Дата изменения') - is_published = models.BooleanField(default=True, verbose_name='Опубликован') - - def __str__(self): - return self.title - - def get_absolute_url(self): - return reverse('post', kwargs={'post_id': self.pk}) - - class Meta: - verbose_name = 'Проекты' - verbose_name_plural = 'Проекты' - ordering = ['time_create', 'title'] - - -class Home(models.Model): - title = models.CharField(max_length=255, verbose_name='Наименование') - content = models.TextField(blank=True, verbose_name='Статья') - home_image = models.ImageField(upload_to="home_image/%Y/%m/%d/", verbose_name='Фото') - time_create = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания') - time_update = models.DateTimeField(auto_now=True, verbose_name='Дата изменения') - is_published = models.BooleanField(default=True, verbose_name='Опубликован') - - def __str__(self): - return self.title - - def get_absolute_url(self): - return reverse('post', kwargs={'post_id': self.pk}) - - class Meta: - verbose_name = 'Главная страница' - verbose_name_plural = 'Главная страница' - ordering = ['time_create', 'title'] - - -class CallbackRequest(models.Model): - name = models.CharField(max_length=100, verbose_name='Имя') - phone = models.CharField(max_length=20, verbose_name='Телефон') - email = models.EmailField(blank=True, null=True, verbose_name='Электронная почта') # Сделать необязательным - question = models.TextField(blank=True, verbose_name='Ваш вопрос') # Сделать необязательным - time_create = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания') - is_processed = models.BooleanField(default=False, verbose_name='Обработано') - is_read = models.BooleanField(default=False, verbose_name='Прочитано') - notification_sent = models.BooleanField(default=False, verbose_name='Уведомление отправлено') - - def __str__(self): - return f"{self.name} - {self.phone}" - - class Meta: - verbose_name = 'Заявка на звонок' - verbose_name_plural = 'Заявки на звонок' - ordering = ['-time_create'] - - -# Сигнал для отправки уведомления при создании заявки -@receiver(post_save, sender=CallbackRequest) -def send_callback_email_notification(sender, instance, created, **kwargs): - if created and not instance.notification_sent: - # Отправляем email уведомление - success = send_callback_notification(instance) - if success: - instance.notification_sent = True - # Сохраняем без повторного вызова сигнала - sender.objects.filter(pk=instance.pk).update(notification_sent=True) - - -class PageView(models.Model): - url = models.CharField(max_length=500) - timestamp = models.DateTimeField(default=timezone.now) - ip_address = models.GenericIPAddressField() - user_agent = models.TextField(blank=True) - referer = models.CharField(max_length=500, blank=True) - - class Meta: - indexes = [ - models.Index(fields=['url', 'timestamp']), - models.Index(fields=['timestamp']), - ] - - -class Visitor(models.Model): - ip_address = models.GenericIPAddressField() - first_visit = models.DateTimeField(default=timezone.now) - last_visit = models.DateTimeField(default=timezone.now) - visit_count = models.IntegerField(default=1) - - class Meta: - indexes = [ - models.Index(fields=['ip_address']), - ] - - -@receiver([post_save, post_delete], sender=Home) -@receiver([post_save, post_delete], sender=Solution) -@receiver([post_save, post_delete], sender=Competence) -@receiver([post_save, post_delete], sender=Recall) -def clear_sitemap_cache(sender, **kwargs): - """Очищаем кэш sitemap при изменении контента""" - cache.delete('sitemap_cache') -======= from django.db import models from django.urls import reverse from django.utils import timezone @@ -334,4 +178,3 @@ class Visitor(models.Model): def clear_sitemap_cache(sender, **kwargs): """Очищаем кэш sitemap при изменении контента""" cache.delete('sitemap_cache') ->>>>>>> master diff --git a/programmer/sitemaps.py b/programmer/sitemaps.py index 16fe364..e71f587 100644 --- a/programmer/sitemaps.py +++ b/programmer/sitemaps.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD from django.contrib.sitemaps import Sitemap from django.urls import reverse from .models import Home, Solution, Competence, Recall @@ -62,69 +61,4 @@ sitemaps = { 'solutions': SolutionSitemap, 'competence': CompetenceSitemap, 'recall': RecallSitemap, -======= -from django.contrib.sitemaps import Sitemap -from django.urls import reverse -from .models import Home, Solution, Competence, Recall - -class StaticViewSitemap(Sitemap): - priority = 1.0 - changefreq = 'monthly' - - def items(self): - return ['home', 'about', 'solution', 'ability', 'recall'] - - def location(self, item): - return reverse(item) - -class HomeSitemap(Sitemap): - changefreq = 'weekly' - priority = 1.0 - - def items(self): - return Home.objects.filter(is_published=True) - - def lastmod(self, obj): - return obj.time_update - - # УБИРАЕМ метод location - используем default - # Django автоматически сгенерирует правильные URL - -class SolutionSitemap(Sitemap): - changefreq = 'weekly' - priority = 0.9 - - def items(self): - return Solution.objects.filter(is_published=True) - - def lastmod(self, obj): - return obj.time_update - -class CompetenceSitemap(Sitemap): - changefreq = 'monthly' - priority = 0.8 - - def items(self): - return Competence.objects.filter(is_published=True) - - def lastmod(self, obj): - return obj.time_update - -class RecallSitemap(Sitemap): - changefreq = 'monthly' - priority = 0.7 - - def items(self): - return Recall.objects.filter(is_published=True) - - def lastmod(self, obj): - return obj.time_update - -# Упрощаем sitemaps - убираем HomeSitemap если он дублирует главную -sitemaps = { - 'static': StaticViewSitemap, - 'solutions': SolutionSitemap, - 'competence': CompetenceSitemap, - 'recall': RecallSitemap, ->>>>>>> master } \ No newline at end of file diff --git a/programmer/templates/admin/base.html b/programmer/templates/admin/base.html index 42d2eb0..c8f00f5 100644 --- a/programmer/templates/admin/base.html +++ b/programmer/templates/admin/base.html @@ -1,4 +1,3 @@ -<<<<<<< HEAD @@ -77,84 +76,4 @@ {% bootstrap_javascript %} -======= - - - - - - {% block title %}Админ-панель - Статистика{% endblock %} - {% load django_bootstrap5 %} - {% bootstrap_css %} - - - -
-
-
-

{% block page_title %}Админ-панель{% endblock %}

- -
-
-
- -
- {% bootstrap_messages %} - {% block content %} - {% endblock %} -
- - {% bootstrap_javascript %} - ->>>>>>> master \ No newline at end of file diff --git a/programmer/templates/admin/base_site.html b/programmer/templates/admin/base_site.html index 5481d79..58bd451 100644 --- a/programmer/templates/admin/base_site.html +++ b/programmer/templates/admin/base_site.html @@ -1,4 +1,3 @@ -<<<<<<< HEAD {% extends "admin/base.html" %} {% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %} @@ -24,31 +23,4 @@ 📊 Статистика заявок / 📈 Посещения / {{ block.super }} -======= -{% extends "admin/base.html" %} - -{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %} - -{% block branding %} -

{{ site_header|default:_('Django administration') }}

-{% endblock %} - -{% block nav-global %} -{% endblock %} - -{% block userlinks %} - {% load programmer_tags %} - - - {% get_unread_callbacks as unread_callbacks %} - {% if unread_callbacks %} - - 🚨 {{ unread_callbacks }} новых заявок - / - {% endif %} - - 📊 Статистика заявок / - 📈 Посещения / - {{ block.super }} ->>>>>>> master {% endblock %} \ No newline at end of file diff --git a/programmer/templates/admin/callback_stats.html b/programmer/templates/admin/callback_stats.html index 9845dd7..916c167 100644 --- a/programmer/templates/admin/callback_stats.html +++ b/programmer/templates/admin/callback_stats.html @@ -1,4 +1,3 @@ -<<<<<<< HEAD {% extends "admin/base_site.html" %} {% block title %}Статистика заявок{% endblock %} @@ -43,50 +42,4 @@ -======= -{% extends "admin/base_site.html" %} - -{% block title %}Статистика заявок{% endblock %} - -{% block content %} -
-

📊 Статистика заявок на обратный звонок

- -
-
-

📋 Всего заявок

-

{{ stats.total }}

-
- -
-

📅 Сегодня

-

{{ stats.today }}

-
- -
-

📈 За неделю

-

{{ stats.week }}

-
- -
-

🆕 Непрочитанные

-

{{ stats.unread }}

-
- -
-

⏳ В обработке

-

{{ stats.unprocessed }}

-
-
- - -
->>>>>>> master {% endblock %} \ No newline at end of file diff --git a/programmer/templates/admin/statistics.html b/programmer/templates/admin/statistics.html index f0f8643..4a1650d 100644 --- a/programmer/templates/admin/statistics.html +++ b/programmer/templates/admin/statistics.html @@ -1,4 +1,3 @@ -<<<<<<< HEAD {% extends 'admin/base.html' %} {% load programmer_tags %} @@ -129,136 +128,4 @@ -======= -{% extends 'admin/base.html' %} -{% load programmer_tags %} - -{% block title %}Статистика посещений{% endblock %} -{% block page_title %}Статистика посещений{% endblock %} - -{% block content %} - -{% get_unread_callbacks as unread_callbacks %} -{% get_today_callbacks as today_callbacks %} -{% if unread_callbacks > 0 %} - -{% endif %} - -
-
-
-
-

📊 Просмотров сегодня

-

{{ today_views }}

-
-
-

📈 Просмотров за неделю

-

{{ weekly_views }}

-
-
-

👥 Уникальных посетителей

-

{{ unique_visitors }}

-
-
-

🕒 Всего просмотров

-

{{ total_views }}

-
- -
-

📞 Заявок сегодня

-

{{ today_callbacks }}

-
-
-

📋 Всего заявок

-

{% get_unread_callbacks %}/{{ total_callbacks }}

- (непрочитанные/всего) -
-
-
-
- - -
-
-
-
-

🔥 Популярные страницы (за неделю)

-
-
- - - - - - - - - {% for page in popular_pages %} - - - - - {% empty %} - - - - {% endfor %} - -
СтраницаПросмотров
- {{ page.url }} - {% if page.url == '/' %} - Главная - {% endif %} - {{ page.views }}
Нет данных за выбранный период
-
-
-
-
- -
-
-
-
-

📋 Последние посещения

-
-
- - - - - - - - - - {% for view in recent_views %} - - - - - - {% empty %} - - - - {% endfor %} - -
ВремяСтраницаIP-адрес
{{ view.timestamp|date:"d.m.Y H:i" }}{{ view.url }}{{ view.ip_address }}
Нет данных
-
-
-
-
->>>>>>> master {% endblock %} \ No newline at end of file diff --git a/programmer/templates/emails/callback_notification.html b/programmer/templates/emails/callback_notification.html index e91be02..4e7cdd8 100644 --- a/programmer/templates/emails/callback_notification.html +++ b/programmer/templates/emails/callback_notification.html @@ -1,4 +1,3 @@ -<<<<<<< HEAD @@ -55,62 +54,4 @@ -======= - - - - - - - - -
-
-

🚨 Новая заявка на сайте

-

Требуется ваше внимание!

-
- -
-
- ⚠️ Срочно! Пользователь оставил заявку на обратный звонок. -
- -
-

📋 Информация о заявке:

-

👤 Имя: {{ callback.name }}

-

📞 Телефон: {{ callback.phone }}

- {% if callback.email %} -

📧 Email: {{ callback.email }}

- {% endif %} - {% if callback.question %} -

❓ Вопрос:
{{ callback.question }}

- {% endif %} -

🕒 Время отправки: {{ callback.time_create|date:"d.m.Y H:i" }}

-
- - - -

Не забудьте отметить заявку как обработанную после связи с клиентом!

-
- - -
- ->>>>>>> master \ No newline at end of file diff --git a/programmer/templates/emails/daily_summary.html b/programmer/templates/emails/daily_summary.html index 86d307d..7886975 100644 --- a/programmer/templates/emails/daily_summary.html +++ b/programmer/templates/emails/daily_summary.html @@ -1,4 +1,3 @@ -<<<<<<< HEAD @@ -58,65 +57,4 @@ -======= - - - - - - - - -
-
-

📊 Ежедневная сводка

-

Статистика заявок за {{ yesterday|date:"d.m.Y" }}

-
- -
-
-
-

📅 Вчерашние заявки

-

{{ yesterday_callbacks }}

-
- -
-

⏳ Ожидают обработки

-

{{ unprocessed_callbacks }}

-
-
- - {% if unprocessed_callbacks > 0 %} -
- ⚠️ Внимание! У вас есть {{ unprocessed_callbacks }} необработанных заявок. -
- {% endif %} - - - -

Не забудьте обработать все pending заявки!

-
- - -
- ->>>>>>> master \ No newline at end of file diff --git a/programmer/templates/programmer/about.html b/programmer/templates/programmer/about.html index 1515dd4..696fa6d 100644 --- a/programmer/templates/programmer/about.html +++ b/programmer/templates/programmer/about.html @@ -1,4 +1,3 @@ -<<<<<<< HEAD {% extends 'programmer/base.html' %} {% load django_bootstrap5 %} @@ -152,159 +151,4 @@ } -======= -{% extends 'programmer/base.html' %} -{% load django_bootstrap5 %} - -{% block content %} - - -
-
-

Николай Сердюк

-

Разработчик 1С

-
- -
-

🚀 Опыт работы

-

Более 10 лет успешной работы в разработке и сопровождении систем на платформе 1С

- -
-

Основные направления:

-
-
-

💻 Разработка

-
    -
  • Разработка и доработка конфигураций 1С
  • -
  • Создание внешних обработок и отчетов
  • -
  • Кастомизация под бизнес-процессы
  • -
-
-
-

🔗 Интеграция

-
    -
  • Интеграция 1С с веб-сервисами
  • -
  • Связь с сайтами и мобильными приложениями
  • -
  • API и веб-сервисы
  • -
-
-
-

⚡ Оптимизация

-
    -
  • Оптимизация бизнес-процессов
  • -
  • Ускорение работы баз данных
  • -
  • Автоматизация рутинных операций
  • -
-
-
-
-
- -
-

🛠 Технологии и навыки

-
-
-

🎯 1С Разработка

-
    -
  • 1С:Предприятие 8.3
  • -
  • Управление торговлей
  • -
  • Бухгалтерия предприятия
  • -
  • Зарплата и управление персоналом
  • -
  • Внешние обработки и отчеты
  • -
-
-
-

🔧 Дополнительные технологии

-
    -
  • SQL и оптимизация запросов
  • -
  • Веб-сервисы и API
  • -
  • XML, JSON, REST
  • -
  • Системное администрирование
  • -
-
-
-
- -
-

📈 Проекты и достижения

-

Успешно реализовал более 50 проектов различной сложности

- -
-
-

🏆 Ключевые проекты

-
    -
  • Автоматизация учетных систем для предприятий
  • -
  • Интеграция 1С с сайтами и мобильными приложениями
  • -
  • Разработка кастомизированных отчетов и дашбордов
  • -
  • Оптимизация производительности баз данных
  • -
-
-
-
- -
-

📞 Контакты

-
-
-
-

📧 Электронная почта

-

{{ CONTACT_EMAIL }}

-
-
-

📱 Телефон

-

{{ CONTACT_PHONE }}

-
-
-

💬 Telegram

-

@odinesina_prog

-
-
-
-
- - -
- - - ->>>>>>> master {% endblock %} \ No newline at end of file diff --git a/programmer/templates/programmer/base.html b/programmer/templates/programmer/base.html index 933f594..ff10cda 100644 --- a/programmer/templates/programmer/base.html +++ b/programmer/templates/programmer/base.html @@ -1,559 +1,3 @@ -<<<<<<< HEAD -{% load static %} -{% load programmer_tags %} -{% load django_bootstrap5 %} - - - - {{title}} - Программист 1С - - - - - - - - - - - - - - - - - - - - - - - {% bootstrap_css %} - - - - - - - - - - - - {% block extra_css %} - - {% endblock %} - - - - - - - - - - - - - - - {% block mainmenu %} -
-
- -
-
- - -
-
-
-

Меню

- -
- - - -
- - - Telegram - - -
- - -
-
-
- {% endblock mainmenu %} - - -
-
-
- - {% block breadcrumbs %} - - {% endblock %} - - - {% bootstrap_messages %} - - -
- {% block content %} - {% endblock %} -
-
-
-
- - -
-
- -
-
- - {% bootstrap_javascript %} - - - - {% block extra_js %} - - {% endblock %} - -======= {% load static %} {% load programmer_tags %} {% load django_bootstrap5 %} @@ -1131,5 +575,4 @@ } ->>>>>>> master \ No newline at end of file diff --git a/programmer/templates/programmer/callback.html b/programmer/templates/programmer/callback.html index 7528544..9106615 100644 --- a/programmer/templates/programmer/callback.html +++ b/programmer/templates/programmer/callback.html @@ -1,4 +1,3 @@ -<<<<<<< HEAD {% extends 'programmer/base.html' %} {% load django_bootstrap5 %} @@ -6,13 +5,4 @@ -======= -{% extends 'programmer/base.html' %} -{% load django_bootstrap5 %} - -{% block content %} - - - ->>>>>>> master {% endblock %} \ No newline at end of file diff --git a/programmer/templates/programmer/competence.html b/programmer/templates/programmer/competence.html index 19e565f..2c261b5 100644 --- a/programmer/templates/programmer/competence.html +++ b/programmer/templates/programmer/competence.html @@ -1,76 +1,3 @@ -<<<<<<< HEAD -{% extends 'programmer/base.html' %} -{% load django_bootstrap5 %} -{% load static %} - -{% block extra_css %} - -{% endblock %} - -{% block content %} - - -
- {% for p in posts %} -
-
- {% if p.photo %} -
-
- {{ p.title }} -
- 🔍 - Нажмите для увеличения -
-
-
- {% endif %} - -
-

{{ p.title }}

-
- {{ p.content|linebreaks }} -
-
-
-
- {% endfor %} -
- -{% if not posts %} -
-

📚 Информация о компетенциях

-

Раздел находится в разработке

- -
-{% endif %} - - - -{% endblock %} - -{% block extra_js %} - -======= {% extends 'programmer/base.html' %} {% load django_bootstrap5 %} {% load static %} @@ -142,5 +69,4 @@ {% block extra_js %} ->>>>>>> master {% endblock %} \ No newline at end of file diff --git a/programmer/templates/programmer/humans.txt b/programmer/templates/programmer/humans.txt index c32412e..7a8f4bc 100644 --- a/programmer/templates/programmer/humans.txt +++ b/programmer/templates/programmer/humans.txt @@ -1,4 +1,3 @@ -<<<<<<< HEAD /* TEAM */ Developer: Николай Сердюк Site: https://nikdizell.ru @@ -11,18 +10,4 @@ Bootstrap /* SITE */ Last update: 2025 Language: Russian -======= -/* TEAM */ -Developer: Николай Сердюк -Site: https://nikdizell.ru -Email: {{ CONTACT_EMAIL }} - -/* THANKS */ -Django Framework -Bootstrap - -/* SITE */ -Last update: 2025 -Language: Russian ->>>>>>> master Doctype: HTML5 \ No newline at end of file diff --git a/programmer/templates/programmer/index.html b/programmer/templates/programmer/index.html index 8539a39..ca59bd6 100644 --- a/programmer/templates/programmer/index.html +++ b/programmer/templates/programmer/index.html @@ -1,4 +1,3 @@ -<<<<<<< HEAD {% extends 'programmer/base.html' %} {% load django_bootstrap5 %} @@ -101,108 +100,4 @@ document.addEventListener('keydown', function(event) { } }); -======= -{% extends 'programmer/base.html' %} -{% load django_bootstrap5 %} - -{% block content %} -
-

🚀 Добро пожаловать!

-

Я профессиональный программист 1С с опытом создания эффективных бизнес-решений

-
- -
- {% autoescape off %} - {% for p in posts %} -
-
-

{{p.title}}

-
-
- {{p.content}} -
-
- -
-
- {% endfor %} - {% endautoescape %} -
- - - - -{% if not posts %} -
-

🚀 Контент скоро появится

-

Мы готовим для вас интересные материалы и кейсы

-
- -
-
-{% endif %} - - ->>>>>>> master {% endblock %} \ No newline at end of file diff --git a/programmer/templates/programmer/recall.html b/programmer/templates/programmer/recall.html index 83a4b8f..faca463 100644 --- a/programmer/templates/programmer/recall.html +++ b/programmer/templates/programmer/recall.html @@ -1,153 +1,3 @@ -<<<<<<< HEAD -{% extends 'programmer/base.html' %} -{% load django_bootstrap5 %} -{% load static %} - -{% block extra_css %} - -{% endblock %} - -{% block content %} - - -
- {% for p in posts %} -
-
-
-
-

{{ p.title }}

- {% if p.time_create %} - - - - {% endif %} -
-
- -
- {% if p.scan %} -
-
- Отзыв от {{ p.title }} -
- 🔍 - Нажмите для увеличения -
-
-
- {% endif %} - -
- {{ p.content|linebreaks }} -
-
-
-
- {% endfor %} -
- -{% if not posts %} -
-

💬 Отзывы клиентов

-

Здесь будут отображаться отзывы от довольных клиентов

- -
-{% endif %} - - - - - -======= {% extends 'programmer/base.html' %} {% load django_bootstrap5 %} {% load static %} @@ -321,5 +171,4 @@ function adjustModalImageSize() { {% block extra_js %} ->>>>>>> master {% endblock %} \ No newline at end of file diff --git a/programmer/templates/programmer/robots.txt b/programmer/templates/programmer/robots.txt index 437205e..32d69b7 100644 --- a/programmer/templates/programmer/robots.txt +++ b/programmer/templates/programmer/robots.txt @@ -1,22 +1,3 @@ -<<<<<<< HEAD -User-agent: * -Allow: / - -# Основной сайт -Sitemap: {{ request.scheme }}://{{ request.get_host }}/sitemap.xml - -# Запрещаем служебные разделы -Disallow: /admin/ -Disallow: /static/admin/ -Disallow: /callback/ -Disallow: /api/ - -# Разрешаем индексацию статических файлов -Allow: /static/ -Allow: /media/ - -# Указываем главное зеркало -======= User-agent: * Allow: / @@ -35,5 +16,4 @@ Allow: /static/ Allow: /media/ # Указываем главное зеркало ->>>>>>> master Host: {{ request.scheme }}://{{ request.get_host }} \ No newline at end of file diff --git a/programmer/templates/programmer/sitemap.xml b/programmer/templates/programmer/sitemap.xml index fe18a95..62e1b06 100644 --- a/programmer/templates/programmer/sitemap.xml +++ b/programmer/templates/programmer/sitemap.xml @@ -1,4 +1,3 @@ -<<<<<<< HEAD @@ -10,17 +9,4 @@ {% if url.priority %}{{ url.priority }}{% endif %} {% endfor %} -======= - - -{% for url in urlset %} - - {{ url.location }} - {% if url.lastmod %}{{ url.lastmod|date:"Y-m-d" }}{% endif %} - {% if url.changefreq %}{{ url.changefreq }}{% endif %} - {% if url.priority %}{{ url.priority }}{% endif %} - -{% endfor %} ->>>>>>> master \ No newline at end of file diff --git a/programmer/templates/programmer/solution.html b/programmer/templates/programmer/solution.html index e184af4..babc513 100644 --- a/programmer/templates/programmer/solution.html +++ b/programmer/templates/programmer/solution.html @@ -1,74 +1,3 @@ -<<<<<<< HEAD -{% extends 'programmer/base.html' %} -{% load django_bootstrap5 %} -{% load static %} - -{% block extra_css %} - -{% endblock %} - -{% block content %} -

{{title}}

- -
- {% autoescape off %} - {% for p in posts %} -
  • -
    -

    {{p.title}}

    - -
    -
    -
    - 📋 Описание задачи - -
    -
    - {{p.description}} -
    -
    - -
    -
    - 🔧 Описание решения - -
    -
    - {{p.implementation}} -
    -
    - -
    -
    - ✅ Результат - -
    -
    - {{p.closing}} -
    -
    -
    - -
    -

    Опубликовано: {{p.time_create|date:"d.m.Y"}}

    -
    -
    -
  • - {% endfor %} - {% endautoescape %} -
    - -{% if not posts %} -
    -

    Примеры решений скоро появятся

    -

    Мы готовим для вас интересные кейсы и решения

    -
    -{% endif %} - - - - -======= {% extends 'programmer/base.html' %} {% load django_bootstrap5 %} {% load static %} @@ -164,5 +93,4 @@ ->>>>>>> master {% endblock %} \ No newline at end of file diff --git a/programmer/templatetags/programmer_tags.py b/programmer/templatetags/programmer_tags.py index 67afdc1..b7b1498 100644 --- a/programmer/templatetags/programmer_tags.py +++ b/programmer/templatetags/programmer_tags.py @@ -1,19 +1,3 @@ -<<<<<<< HEAD -from django import template -from programmer.models import * - - -register = template.Library() - -@register.simple_tag(name='competence') -def get_competence(): - return Competence.objects.all() - - -@register.simple_tag(name='recall') -def get_recall(): - return Recall.objects.all() -======= from django import template from ..models import CallbackRequest @@ -28,4 +12,3 @@ def get_today_callbacks(): from django.utils import timezone today = timezone.now().date() return CallbackRequest.objects.filter(time_create__date=today).count() ->>>>>>> master diff --git a/programmer/tests.py b/programmer/tests.py index 0e7885b..7ce503c 100644 --- a/programmer/tests.py +++ b/programmer/tests.py @@ -1,9 +1,3 @@ -<<<<<<< HEAD from django.test import TestCase # Create your tests here. -======= -from django.test import TestCase - -# Create your tests here. ->>>>>>> master diff --git a/programmer/urls.py b/programmer/urls.py index 0547193..ed69c18 100644 --- a/programmer/urls.py +++ b/programmer/urls.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD from django.contrib import admin from django.urls import path, include from django.conf import settings @@ -25,32 +24,4 @@ urlpatterns = [ if settings.DEBUG: -======= -from django.contrib import admin -from django.urls import path, include -from django.conf import settings -from django.conf.urls.static import static -from .views import * -from django.contrib.sitemaps.views import sitemap -from .sitemaps import sitemaps - - -urlpatterns = [ - path('', index, name='home'), - path('about/', about, name='about'), - path('solutions/', solution, name='solution'), - path('competence/', ability, name='ability'), - path('recall/', recall, name='recall'), - path('post//', show_post, name='post'), - path('callback/', callback_request, name='callback'), - path('admin/statistics/', statistics_view, name='statistics'), - # Sitemap - path('sitemap.xml', sitemap, {'sitemaps': sitemaps}, - name='django.contrib.sitemaps.views.sitemap'), - path('robots.txt', robots_txt, name='robots'), -] - - -if settings.DEBUG: ->>>>>>> master urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \ No newline at end of file diff --git a/programmer/views.py b/programmer/views.py index 7601fe6..999b213 100644 --- a/programmer/views.py +++ b/programmer/views.py @@ -1,258 +1,3 @@ -<<<<<<< HEAD -from django.http import HttpResponse, HttpResponseNotFound -from .models import * -from django.shortcuts import render, redirect -from django.contrib import messages -from .models import CallbackRequest # Импортируем из models, а не forms -from .forms import CallbackForm -from django.utils import timezone -from datetime import timedelta -from .models import PageView, Visitor -from django.db.models import Count -from django.contrib.auth.decorators import login_required, user_passes_test -from django.views.decorators.http import require_GET - - -menu = [ - {'title': "Главная", 'url_name': 'home'}, - {'title': "Проекты", 'url_name': 'solution'}, - {'title': "Компетенции", 'url_name': 'ability'}, - {'title': "Отзывы", 'url_name': 'recall'}, - {'title': "Обо мне", 'url_name': 'about'} - ] - - -# === ДОБАВЬТЕ ЭТИ ФУНКЦИИ ЗДЕСЬ === - -def get_client_ip(request): - """Получаем реальный IP клиента""" - x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') - if x_forwarded_for: - ip = x_forwarded_for.split(',')[0] - else: - ip = request.META.get('REMOTE_ADDR') - return ip - - -def should_track_request(request): - """Определяем, нужно ли отслеживать запрос""" - - client_ip = get_client_ip(request) - path = request.path - - # Игнорируемые пути (Nextcloud специфичные) - nextcloud_paths = [ - '/index.php', - '/status.php', - '/cron', - '/remote.php', - '/ocs', - '/apps/', - '/custom_apps/', - ] - - # Игнорируемые IP (Docker сети) - docker_ips = [ - '192.168.64.1', - '192.168.65.1', - '172.17.0.1', - '172.18.0.1', - '172.19.0.1', - ] - - # Игнорируем статические файлы и админку - if path.startswith('/static/') or path.startswith('/admin/'): - return False - - # Не отслеживаем Nextcloud и Docker запросы - if any(path.startswith(p) for p in nextcloud_paths): - return False - if client_ip in docker_ips: - return False - - return True - - -def track_page_view(request): - """Основная функция отслеживания просмотров""" - if not should_track_request(request): - return - - try: - PageView.objects.create( - url=request.path, - ip_address=get_client_ip(request), - user_agent=request.META.get('HTTP_USER_AGENT', '')[:500], - referer=request.META.get('HTTP_REFERER', '')[:500], - ) - except Exception as e: - print(f"Error tracking page: {e}") - - -def track_view(view_func): - """Декоратор для отслеживания просмотров страниц""" - from functools import wraps - - @wraps(view_func) - def _wrapped_view(request, *args, **kwargs): - # Отслеживаем просмотр перед выполнением view - track_page_view(request) - return view_func(request, *args, **kwargs) - - return _wrapped_view - - -@track_view -def index(request): - posts = Home.objects.filter(is_published=True) - context = { - 'posts': posts, - 'menu': menu, - 'title': "Главная страница", - 'meta_description': "Профессиональный программист 1С с более чем 10-летним опытом. Разработка, интеграция и оптимизация систем 1С. Закажите консультацию.", - 'meta_keywords': "программист 1С, разработка 1С, интеграция 1С, оптимизация 1С, 1С предприятие 8.3", - 'form': CallbackForm() - } - return render(request, 'programmer/index.html', context=context) - - -@track_view -def about(request): - context = { - 'menu': menu, - 'title': "Обо мне - Программист 1С", - 'meta_description': "Николай Сердюк - профессиональный программист 1С с более чем 10-летним опытом. Разработка, интеграция, оптимизация бизнес-процессов.", - 'meta_keywords': "программист 1С Николай Сердюк, опыт работы 1С, компетенции 1С, проекты 1С" - } - return render(request, 'programmer/about.html', context=context) - - -@track_view -def solution(request): - posts = Solution.objects.filter(is_published=True) - context = { - 'posts': posts, - 'menu': menu, - 'title': "Проекты" - } - return render(request, 'programmer/solution.html', context=context) - - -@track_view -def ability(request): - posts = Competence.objects.filter(is_published=True) - context = { - 'posts': posts, - 'menu': menu, - 'title': "Компетенции" - } - return render(request, 'programmer/competence.html', context=context) - - -@track_view -def recall(request): - posts = Recall.objects.filter(is_published=True) - context = { - 'posts': posts, - 'menu': menu, - 'title': "Отзывы" - } - return render(request, 'programmer/recall.html', context=context) - - -def show_post(request, post_id): - return HttpResponse(f"Отображение № {post_id}") - - -def pageNotFound(request, exception): - return HttpResponseNotFound('

    Страница не найдена

    ') - - -def callback_request(request): - if request.method == 'POST': - form = CallbackForm(request.POST) - if form.is_valid(): - # Сохраняем заявку через форму - form.save() - messages.success(request, '✅ Ваша заявка успешно отправлена! Я свяжусь с вами в ближайшее время.') - return redirect('home') - else: - # Если форма невалидна, показываем ошибки - for field, errors in form.errors.items(): - for error in errors: - messages.error(request, f'❌ Ошибка в поле {form.fields[field].label}: {error}') - return redirect('home') - - # Если GET запрос, просто показываем главную страницу - return redirect('home') - - -def is_admin(user): - return user.is_staff - - -def is_staff(user): - return user.is_staff - - -@login_required -@user_passes_test(is_staff) -def statistics_view(request): - today = timezone.now().date() - week_ago = today - timedelta(days=7) - - # Статистика за сегодня - today_views = PageView.objects.filter( - timestamp__date=today - ).count() - - # Статистика за неделю - weekly_views = PageView.objects.filter( - timestamp__date__gte=week_ago - ).count() - - # Всего просмотров - total_views = PageView.objects.count() - - # Популярные страницы за неделю - popular_pages = PageView.objects.filter( - timestamp__date__gte=week_ago - ).values('url').annotate( - views=Count('id') - ).order_by('-views')[:10] - - # Уникальные посетители за неделю - unique_visitors = Visitor.objects.filter( - last_visit__date__gte=week_ago - ).count() - - # Последние посещения - recent_views = PageView.objects.select_related().order_by('-timestamp')[:20] - - today = timezone.now().date() - total_callbacks = CallbackRequest.objects.count() - today_callbacks = CallbackRequest.objects.filter(time_create__date=today).count() - unread_callbacks = CallbackRequest.objects.filter(is_read=False).count() - - context = { - 'today_views': today_views, - 'weekly_views': weekly_views, - 'total_views': total_views, - 'unique_visitors': unique_visitors, - 'popular_pages': popular_pages, - 'recent_views': recent_views, - 'total_callbacks': total_callbacks, - 'today_callbacks': today_callbacks, - 'unread_callbacks': unread_callbacks, - } - - return render(request, 'admin/statistics.html', context) - - -@require_GET -def robots_txt(request): - return render(request, 'robots.txt', content_type='text/plain') -======= from django.http import HttpResponse, HttpResponseNotFound from .models import * from django.shortcuts import render, redirect @@ -512,4 +257,3 @@ def statistics_view(request): @require_GET def robots_txt(request): return render(request, 'robots.txt', content_type='text/plain') ->>>>>>> master