From 1360bc18e1632b3836a9b38af213e68dbdc5f5a9 Mon Sep 17 00:00:00 2001 From: NikDizell Date: Wed, 12 Nov 2025 14:48:46 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=81=D1=82=D0=B8=D0=BA=D1=83=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=81=D0=B0=D0=B9=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__pycache__/settings.cpython-310.pyc | Bin 2706 -> 2748 bytes OneCprogsite/OneCprogsite/settings.py | 1 + .../__pycache__/admin.cpython-310.pyc | Bin 1568 -> 2062 bytes .../__pycache__/middleware.cpython-310.pyc | Bin 0 -> 1903 bytes .../__pycache__/models.cpython-310.pyc | Bin 4480 -> 5531 bytes .../__pycache__/urls.cpython-310.pyc | Bin 786 -> 848 bytes .../__pycache__/views.cpython-310.pyc | Bin 2635 -> 3874 bytes OneCprogsite/programmer/admin.py | 11 ++ OneCprogsite/programmer/middleware.py | 54 ++++++++++ .../migrations/0011_visitor_pageview.py | 41 +++++++ .../0011_visitor_pageview.cpython-310.pyc | Bin 0 -> 1365 bytes OneCprogsite/programmer/models.py | 27 +++++ .../programmer/templates/admin/base.html | 79 ++++++++++++++ .../programmer/templates/admin/base_site.html | 15 +++ .../templates/admin/statistics.html | 100 ++++++++++++++++++ OneCprogsite/programmer/urls.py | 1 + OneCprogsite/programmer/views.py | 62 ++++++++++- 17 files changed, 389 insertions(+), 2 deletions(-) create mode 100644 OneCprogsite/programmer/__pycache__/middleware.cpython-310.pyc create mode 100644 OneCprogsite/programmer/middleware.py create mode 100644 OneCprogsite/programmer/migrations/0011_visitor_pageview.py create mode 100644 OneCprogsite/programmer/migrations/__pycache__/0011_visitor_pageview.cpython-310.pyc create mode 100644 OneCprogsite/programmer/templates/admin/base.html create mode 100644 OneCprogsite/programmer/templates/admin/base_site.html create mode 100644 OneCprogsite/programmer/templates/admin/statistics.html diff --git a/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc b/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc index dd9dd5edb56fcadbe7d93c6bbb29d52be713e1fc..d2b1f956756db80826830de90264630b90be97f5 100644 GIT binary patch delta 72 zcmbOvx<`~ZpO=@50SJnVMKX;y@@6nIa%?VRPG*$XC@9KLFG|eKO)b*P%}hzjNi9z- aO4SQUOivBVOfBDhj-{HFk$bWimj?jVUKPdw delta 40 ucmdlZI!Tl_pO=@50SGpz3uQ8GN7l@qtB5)wid!ZO)uYLw8h>j2=OXWa`)U2hWMh! z4^Q>DewTaBo0^den|h44sm2r6sV8NnwLxpmJ<>7OfPTv(Qa zQDx`0EX^*dm^+LIgvXSYU8Hcn``@qbZ?Dfo!|u!tM#i|wxXrjlaEY!OEKh4Rl^LAQ zHoIN?N7fE-G-BmP{CuPTkgJV}eX7`qjR;C8sX&1bnKV2(%F|^LyxvjQ*3AC$dvJVr Xk7kijkb0@&qf`be%peI9NFasZ)?JP| delta 133 zcmeAZSir-V&&$ij00hNN0-1l#jfFqSBm1Q9lBSR`9n8%ySip1kf zWkcfer?P{1DSW{Un*5s>i&>ccGzBJ`vd2wc#O@;_0W_b7frC+qS%?D!IXFZZ`8fC( I`51*50p8UaX#fBK diff --git a/OneCprogsite/programmer/__pycache__/middleware.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/middleware.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9fc794eb4083d9587c0f5159bf2f878a26a59948 GIT binary patch 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 literal 0 HcmV?d00001 diff --git a/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc index d55c9071dc286b2dc1f18fc02a6fcf6c83f9f4b7..cbbb6faaf1fc657fa97f32a213833731e604716e 100644 GIT binary patch literal 5531 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 diff --git a/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc index 63828751301d6fe6111ed2f4cddc55db222ef550..a20925c4ec9343fff948721174164c39ea66c388 100644 GIT binary patch delta 198 zcmbQlc7aVhpO=@50SI)9L^2OEF)%y^agYHIkmCTv#fK(pPc}(qP7zBLOc77v>}5{p zh!RR=%Mvb%PZdh#0J21YSTseVm&u$VN+?A#m;r<}r6xW*Eng*=n39{Br(ax>Sdv*> zl9^nre~SyjnY@uvm{DxGe!6e&)g!W6}*H2FP~G#3ve M%MUhg2}YLx0HKyMxBvhE delta 150 zcmcb>Hi=C;pO=@50SF={2xQhXF)%y^agYHwkmCTv#oH!oPu56hj}lB}%MvPzOchM! z0J4OESR_TPm&u$VN-#w{m;r<}B_@74EuzVIi#H`dximL5uOz-GKflCJQ*`nN#yOMc gGU>9(1C1<_pL~HSicw**HnTJb%TG2g2}YLx021*dM*si- diff --git a/OneCprogsite/programmer/__pycache__/views.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/views.cpython-310.pyc index e43f2d66eb93f351bc7dbc8e8522d6c67bfa2f97..8ae32e43c46199bd7f9a0ec858984f505439d1a3 100644 GIT binary patch literal 3874 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 wrr& 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>6 + + + + + {% block title %}Админ-панель - Статистика{% endblock %} + {% load django_bootstrap5 %} + {% bootstrap_css %} + + + +
+
+
+

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

+ +
+
+
+ +
+ {% bootstrap_messages %} + {% block content %} + {% endblock %} +
+ + {% bootstrap_javascript %} + + \ No newline at end of file diff --git a/OneCprogsite/programmer/templates/admin/base_site.html b/OneCprogsite/programmer/templates/admin/base_site.html new file mode 100644 index 0000000..5bc87fe --- /dev/null +++ b/OneCprogsite/programmer/templates/admin/base_site.html @@ -0,0 +1,15 @@ +{% 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 %} + 📊 Статистика / + {{ block.super }} +{% endblock %} \ No newline at end of file diff --git a/OneCprogsite/programmer/templates/admin/statistics.html b/OneCprogsite/programmer/templates/admin/statistics.html new file mode 100644 index 0000000..ca01039 --- /dev/null +++ b/OneCprogsite/programmer/templates/admin/statistics.html @@ -0,0 +1,100 @@ +{% extends 'admin/base.html' %} + +{% block title %}Статистика посещений{% endblock %} +{% block page_title %}Статистика посещений{% endblock %} + +{% block content %} +
+
+
+
+

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

+

{{ today_views }}

+
+
+

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

+

{{ weekly_views }}

+
+
+

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

+

{{ unique_visitors }}

+
+
+

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

+

{{ total_views }}

+
+
+
+
+ +
+
+
+
+

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

+
+
+ + + + + + + + + {% 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 }}
Нет данных
+
+
+
+
+{% endblock %} \ No newline at end of file diff --git a/OneCprogsite/programmer/urls.py b/OneCprogsite/programmer/urls.py index 2bec85a..51e8c5a 100644 --- a/OneCprogsite/programmer/urls.py +++ b/OneCprogsite/programmer/urls.py @@ -12,6 +12,7 @@ urlpatterns = [ path('recall/', recall, name='recall'), path('post//', show_post, name='post'), path('callback/', callback_request, name='callback'), + path('admin/statistics/', statistics_view, name='statistics'), ] if settings.DEBUG: diff --git a/OneCprogsite/programmer/views.py b/OneCprogsite/programmer/views.py index b1c9d35..45725c4 100644 --- a/OneCprogsite/programmer/views.py +++ b/OneCprogsite/programmer/views.py @@ -1,10 +1,14 @@ from django.http import HttpResponse, HttpResponseNotFound -from django.shortcuts import render 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 menu = [ @@ -89,4 +93,58 @@ def callback_request(request): return redirect('home') # Если GET запрос, просто показываем главную страницу - return redirect('home') \ No newline at end of file + 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] + + 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, + } + + return render(request, 'admin/statistics.html', context)