From cfd318955bfbbf64424b532ea7e189edc7b2fcf8 Mon Sep 17 00:00:00 2001 From: NikDizell Date: Wed, 12 Nov 2025 17:55:07 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=BF=D1=82=D0=B8=D0=BC=D0=B8=D0=B7?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BE=D0=B4=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=B8=D1=81=D0=BA=D0=BE=D0=B2=D1=83=D1=8E=20=D0=B2=D1=8B=D0=B4?= =?UTF-8?q?=D0=B0=D1=87=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__pycache__/settings.cpython-310.pyc | Bin 2764 -> 2811 bytes OneCprogsite/OneCprogsite/settings.py | 2 + .../__pycache__/models.cpython-310.pyc | Bin 5531 -> 6021 bytes .../__pycache__/sitemaps.cpython-310.pyc | Bin 0 -> 2399 bytes .../__pycache__/urls.cpython-310.pyc | Bin 848 -> 1067 bytes .../__pycache__/views.cpython-310.pyc | Bin 5861 -> 6958 bytes .../programmer/management/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 178 bytes .../management/commands/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 187 bytes .../__pycache__/test_sitemap.cpython-310.pyc | Bin 0 -> 1251 bytes .../management/commands/test_sitemap.py | 27 +++++++ OneCprogsite/programmer/models.py | 12 +++ OneCprogsite/programmer/sitemaps.py | 64 +++++++++++++++ .../templates/programmer/about.html | 33 ++++++++ .../programmer/templates/programmer/base.html | 74 ++++++++++++++++++ .../templates/programmer/humans.txt | 13 +++ .../templates/programmer/robots.txt | 18 +++++ .../templates/programmer/sitemap.xml | 12 +++ OneCprogsite/programmer/urls.py | 8 ++ OneCprogsite/programmer/views.py | 12 ++- 21 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 OneCprogsite/programmer/__pycache__/sitemaps.cpython-310.pyc create mode 100644 OneCprogsite/programmer/management/__init__.py create mode 100644 OneCprogsite/programmer/management/__pycache__/__init__.cpython-310.pyc create mode 100644 OneCprogsite/programmer/management/commands/__init__.py create mode 100644 OneCprogsite/programmer/management/commands/__pycache__/__init__.cpython-310.pyc create mode 100644 OneCprogsite/programmer/management/commands/__pycache__/test_sitemap.cpython-310.pyc create mode 100644 OneCprogsite/programmer/management/commands/test_sitemap.py create mode 100644 OneCprogsite/programmer/sitemaps.py create mode 100644 OneCprogsite/programmer/templates/programmer/humans.txt create mode 100644 OneCprogsite/programmer/templates/programmer/robots.txt create mode 100644 OneCprogsite/programmer/templates/programmer/sitemap.xml diff --git a/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc b/OneCprogsite/OneCprogsite/__pycache__/settings.cpython-310.pyc index 1089903b2a45a0629c675a7703e426a0c8931dff..b93c66dffb1acadc192f64b240db8e0e159ab8db 100644 GIT binary patch delta 71 zcmX>j`dgGYpO=@50SG#0i)6NM>7GcHNJ>^>UV6S>a(-S(QD%}}ac0Tn a2TUStnI);Yi3OX>nK{@Q`6f4T`2YYMj~0{w delta 39 tcmew@dPbBtpO=@50SGe7MKZlM^7b$>a!#JbbZ_%=W_ET)p2_REd;rkl3akJC diff --git a/OneCprogsite/OneCprogsite/settings.py b/OneCprogsite/OneCprogsite/settings.py index b2bd6d9..65ac19e 100644 --- a/OneCprogsite/OneCprogsite/settings.py +++ b/OneCprogsite/OneCprogsite/settings.py @@ -40,6 +40,8 @@ INSTALLED_APPS = [ 'programmer.apps.ProgrammerConfig', 'django_bootstrap5', 'django_extensions', + 'django.contrib.sites', + 'django.contrib.sitemaps', ] MIDDLEWARE = [ diff --git a/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/models.cpython-310.pyc index cbbb6faaf1fc657fa97f32a213833731e604716e..f6d816b274cd3530c58be7387d8307a9439de357 100644 GIT binary patch literal 6021 zcmc&&+jARN8Q)#qR?%Q`o=a3g3D8KLQ%93L_xYII7b3UE# zI~SdEzTbB_$19Zz3O>*LY20~fyQ2Jqn88mD%nXXZO;r@8Fx6EWs;R0}*IccUGE=gi za?_2BnUVFhn{DLGTthc?$!FYrqhJFugJg`2Lo%L7#(9C~xL()z zD4V#Vt#Org+{ikvOdQ+BwqH~(sPWgFU^|W|Q#C4 zPn}3Jm1!(>MKd$tvMkLqEDJ6NPNzd=d2o4f1+*1d5nM6h3|0bXfGeS`%tpYKS%r;W zRLl`pWn=iILmy`oIKGJsnmNk0Vawa2>|tKBUHATbSWJ5xNO-OL^YHC(IlLFHgztpQ z-PgjE?$sqNDm3gfmdl&(Fo3VJv6N5wKs_%xkuzo7>+V$R`ctE_*@ZIi(@Md@iBW~kw-l9Lj zf^v)>x7%(YyVhVXYagmpnMHY!1^J0`LOG%=sdG!vcHjgqM>`_*eWUkte$CDvg)V=Gb}tk7o`cmW=^8mVL)y6w2`$23w$g%+SD( zg7j>Gsb-34W}2l~x(;h#86Y*=DJGL1S$~b)K<%F3)_u!PcSZ=W_{oQNV7toLYfu> zf2%woRO?DwO{<0~zDj>RRTW>Nj$bD76(Y3TC_lSsi@gqanOtF%pXX-+$w#@G*9>?w zhzbW9cAdwG;J`3p5=;uBw{4+O!-g;ENvIT=`W^dwG~TraR9cNqw*$Xf;iD{>YYSY@Vyz$)_-8Ca9NLNx%VrD>j8T;XS+tGk|@>0S`?iY?D!j*D-8a zMys``95?(P;@jb!?ytL-;*f`7|69|LYL})_>Fx4EGYo={kcP2yZSF0b#l|?IB90)d zl5r#r#bi3AwQ0#<+LWV&v4^@9-tM07Uf!~e%+ONbr;S8K#{HUbS_F-#>@->~Z@}l< zlF!v#&!=GXK@4XvmPIz_lWSb>%gbuw&8g3(=G61%>HQvZ5c1<<9}(%X^ z>)ordpB`UCU(2Dm^?&fybF@4ONQ2h=p@H%HG_M5Xgq(NFKot8i5@5^AVG?K*al+ri zfR~YK-oxo#MS6=Pq^L-F>TBWhmXSA4>w2Ha8}QDBzOp_L(!Psj5RzgSP22`dWgwhE z@y~#4>Y~$d!x?$^$-*haJ>!cT&y|!(PC5@RcFP5DMR0>|8BTfqeFyg(dE;SYaK{xk z4y&JtMrLu#S+Hv-5A#>s+z;+Etf!p?3I7n@1&RsW_sP-59^o%=rFW2!T!f>(H{Yfh z7ygYT(nnA}b1zXM9QJDW64}F4N{pgkly0_NSLT#$%2UGMK-s^Xgw|Ja<-pMHIcYO} zC%rdz9(guH>=o-+G4ls8k@t~S?6O+Gz2rC}*Z za3hMwO+GXic?vTupu{NO{>Uk<84`M|`%p49gW`V#q^H(?;$Bygw#V*v{Lv|;F;ET` zB5-xD;#h9urbmZ4iK`wR5(UTG?MJ$-Z0yo8o*qc}=N_NXa9V9YOE2`Y^wD8idYsru z>pzTfQQ^gg?YMDno#9lM36H5uEK!i}J8VjFOqqZSuf~19mw;0qH8kBiNCQx$He-KX zN%C)9L*`BG8|*3#;S3Er3er;mtV55#onbo7l%;W=`$Eq37{70o})l zDL5_pSOGx{n?l>?!otzwu7@Y4<6LmD`Q7X#Onnl?r&L8(3}8dYEwijvH9>6~4m}0o z42u74kUlo9r-6VzF4Pzo2}+2Iy{pEkZU7Isf8(_%4Lp?MJ9v~k>fnXK6M|58pPazv ze?EAnkD&$~YtS+I2J%wrj*(0!RV-e?bmC=@Iq@T^KDnN(T}^%lxlf)OXQAouCHg84 z)t5zcyh218DCtZ57{n|dcLd(>PSJkMf@}Bck#PWb@H&sL=w?xNuxehr8Emd0a-e5X zd IsbpOJ4-wbE@c;k- literal 5531 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 literal 0 HcmV?d00001 diff --git a/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc b/OneCprogsite/programmer/__pycache__/urls.cpython-310.pyc index a20925c4ec9343fff948721174164c39ea66c388..b007e842529a6f4f21a330029c569844d1b4b65e 100644 GIT binary patch delta 524 zcmaKp%}&BV5XZNrl+tdYe19l@BzPbsP2}PceE~1tdLh6}NRd+0Rwcdo1RO|@`UboV zXRf}0F&@0>E-nctXEKxDe`hoQWOt*kwXScPI$;sMmfcN?kasQ)Bge!wtMGf(?Y{tl z%uM$T$B+o5L7P#JI#eQk7|S`TAGNPFSU0{$@Z1x$zYiEoenc@(%Kdw<`4a`8Fb%UBQm zkspP2w1^z_kJ)w;{PClQ^JozGestSuCLhxH#%cY#GsrUEo%uHH&H)zz|AQdUo5fop vxtDu}a2znlnA`W7wb3_TH zvSkSu#it6TasXK(KrEUf(aU7c5G9ntDH+U=0>qk9lQkIaC)Y8q7SUw9#ha3!T$-Dj zR}x>8pI_pqDK@!_DOutcYi3?bYDE#q14XB{BGCKA32X8J5a~ZNvwkH00d)VwxBe6JL!9XpG^(?>n~+rX%6W-rVo| z?svZb=XdVyFP)!n^ch~S#{s{4@A~7fXqS8;lD@R&a?U}$iTY%)FGw8JM;FuTs|u~5 zwURHPe#z@-K=OJTL_X;1YoHCZ@wB6_kv7o~@FvFETb+LrvV}jZPLS5ZPwKCP>?quEzf8ygZ}X%`KY!cP=Bb3)ZGk(}#m`qY zgs97O<{ebMs-9F#*9ix$JfTqc`3lJR1pmXcF_--fjKv4mDKTrE7Da2+8WmGwR?LV= zamzX#;!sBenN4h<}4KrY&8th12hA}DR=F^mKE4KZ0>!9uYL zJE53>xK|)9gc4uE3g|U>fKI?DkG+7(_Pr3vzJ*;wQ#mkLpsNl|R%h2ZS0eWNh%)UJ z?DD^b$~7F7oMKU2mmHb{+h?Yr%*~PYVYTE+8yPcGawhdumieK+Qgu={qXSgW#8^CS z#*I|TD>X;-mNFo>C2AU*|t#J-$F{mbWOd-->Z znsXsoG#!*sg;r4KRp&`!62OS-1fizBfEg&aQ?v21(BN!1y$2hG zqrU}v0pOVcB%Bi0tqbBNI!i1e*mD0j+U9oB-o+e(nVgr6OP%P6ZqZ8*X;KqPS^| z+4f;4djSfO=wUCS^b(Mfx->HeSu~l{+1ltqBWp$uo5=**xfK?}itVD>@(OfX08$L0 zaun`N6%eJu29tWx&d{=4t8_v3#wZo>Kt?=0Rx$P)f-_0!~4?yBjj-2uxb*P*zcpezb9i}9hFR`Myo zShJiA@@qA{-WgEe#h5B#NzjDWGkj05b|i5mN09t$>_edY8uck8Lxn@N_Xyd|`~9yi z%c2I6!Hyw0j$|0g2$Eg=2Y(CshTr$^CV5Eb&$&P?KTtjpOb5JfE@@Mhf=Q959ck^)O))v4ly)&M&uA4l)2i?m`xOh6+0a zaz%G|HQ!fvM}t2BL($Zr5jh&yk7XiMj~Og#8Y}})G1IJ;HwT(G?*$JDeF;2zL@p_2jd2qWuZYNwz+)l-* Kf|=6cBYy)tC}}+a delta 1089 zcmZ`%OKTHR6rMAgna1d(lXo&nAL%1C*49Tw5nKtPwlq~E)^<@Tp0SNh8o8OONQ#e& zt_1bEte^`QZbZmNunT{IBJQ#fH@Xx>3ocYVXVjvgGw^-iJ?G4K&b@aY?R+~BteR#( zq33lyTI$c-3TEK=t^PX~O$=h|vWgalJPu>T<0!^Fj$?v(MxRVz5>r=|$t2pCCQe}n z+lXy!#}4AOlg3WWUR9Q0GDErx6P|7(-Hjnnx0CL{h^IS9_YPysTXbR$`^Y4V8!=DZ zg`2RSxEnX)0C5iv;uhjwC+5VR-X*}TxQ)N0W;xtmRPsae9=wuQ)N8QXSm&DtNHylP zF93Tb8uy{QVYIvl7;dck#{s6~XkZ>Dk+GaW!S2+!*RRmOTz#`Pa^`Xzz zmK4;MwMEs{>k8_16^$D{>eeE&>vu-;T2nt$t+}BnYbXfC?HIUxS7illRQFfg~kdg=bh+7r_PU>8k^3UQfLs(v;7u;sB9| z$h)oS)bJk>Y0 z^rpX9EibsG>b%&+1*2b;7W04<)RB zeQokiuXAOQfTpsK{_T?TTnH}2&xq=bn66YDu|+s1r_1HRS+`OazeY8Vc(MNv8nDUb zHro~DhtQIFmt;*P2!a@wm%?|<`@bW85EG4TWCuW49*gd#Kjdb#7(PhprhcmAlu?`@ zEvDsav3dDX#2e;42p;KC{+Yk}JF{Gt4$V#y$g# z%6EyW4!$bkGAuBhV>rujo?%3uOm@RFc|AGSa+v~!e4nhOp35oQ9vb6<3)3w{9h1M%4a diff --git a/OneCprogsite/programmer/management/__init__.py b/OneCprogsite/programmer/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/OneCprogsite/programmer/management/__pycache__/__init__.cpython-310.pyc b/OneCprogsite/programmer/management/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb39175ebba71f6bf41c1f5ceb1c663ed2850326 GIT binary patch literal 178 zcmd1j<>g`kg0wjznIQTxh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o11>#VRJCvLquv z4@$)c6y;~7CYQvdWF_XM=L4zY%#zd?|GZS^f};F%FbBjaO3ckoEsDua%u7s9%}vcK jiHVQT%*!l^kJl@xyv1RYo1apelWGUDu9yi(urL4sDLgKU literal 0 HcmV?d00001 diff --git a/OneCprogsite/programmer/management/commands/__init__.py b/OneCprogsite/programmer/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/OneCprogsite/programmer/management/commands/__pycache__/__init__.cpython-310.pyc b/OneCprogsite/programmer/management/commands/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b2a1355c1f53536173afb8132390db8c931071d GIT binary patch literal 187 zcmd1j<>g`kg0wjznIQTxh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o11*#VRJCvLquv z4@$)c6y;~7CYQvdWF_XM=L4zY%#zd?|GZS^f};F%FbBjaO3ckoEsDua%u7s9%}vcK qiAm1S1@cmgW8&j8^D;}~$Yrd(L?35;)N%Yz>#A>Z+Ebuc(QfT?yt zaKdRuavD*Jdm}S)Gcu=pGh?|GS<^ks?A(c*+>PAai@e;Ad`cb@ZgKk~;kKZsX4K-& z9_hM2!7J%f-FlcPu~p`IQgAprdxJ{k$q=_vycJT3F4OEunG5aimD#8ol!f-;!BAA9 zNQJhai!{ly6#ZQt1{@y1RI4Bai6|$L!D(c2gPR{o#5jXIEbTPG>y;NmRe_qt5Bj1I zGQnsm1qYV{F>Awo22*_n!6~2t$V>o@F*!6oo7}trl*Z;~c0snu>%E>aVH2ylV`Fv( zc%08{tW$zk6T7*!D{E|@(lc^yOnumZwe!iiiGIR~Q(qh73w!Kb(23i;amVhZ{Y!GR z!ARwt>{BxFD5;kk8*l8*ZC(L`6Ysruv@u(c=`lI#G?qTbg1~xEs_hl#iq=0w?%54t<)i(C{{56Z+|S3N8`ZbFB{6Kx-WIulr= z3P7}J+vpg})TcLS$1rFc)A-oTcDR1Tw)s1MS)3ONfbGen5}m2&8obQ Py{cwkCjduR>9YA3+o4T; literal 0 HcmV?d00001 diff --git a/OneCprogsite/programmer/management/commands/test_sitemap.py b/OneCprogsite/programmer/management/commands/test_sitemap.py new file mode 100644 index 0000000..338d65d --- /dev/null +++ b/OneCprogsite/programmer/management/commands/test_sitemap.py @@ -0,0 +1,27 @@ +from django.core.management.base import BaseCommand +from django.contrib.sitemaps import Sitemap +from django.urls import reverse +from programmer.models import Home, Solution, Competence, Recall + + +class Command(BaseCommand): + help = 'Test sitemap generation' + + def handle(self, *args, **options): + from programmer.sitemaps import sitemaps + + self.stdout.write('Testing sitemap generation...') + + for name, sitemap in sitemaps.items(): + self.stdout.write(f'\n{name}:') + items = sitemap().items() + self.stdout.write(f' Items found: {len(items)}') + + for item in items[:3]: # Показываем первые 3 элемента + try: + url = sitemap().location(item) + self.stdout.write(f' - {url}') + except Exception as e: + self.stdout.write(f' - Error: {e}') + + self.stdout.write('\nSitemap test completed!') diff --git a/OneCprogsite/programmer/models.py b/OneCprogsite/programmer/models.py index 5cd7369..065b6aa 100644 --- a/OneCprogsite/programmer/models.py +++ b/OneCprogsite/programmer/models.py @@ -1,6 +1,9 @@ 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 class Recall(models.Model): @@ -125,3 +128,12 @@ class Visitor(models.Model): 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') diff --git a/OneCprogsite/programmer/sitemaps.py b/OneCprogsite/programmer/sitemaps.py new file mode 100644 index 0000000..e71f587 --- /dev/null +++ b/OneCprogsite/programmer/sitemaps.py @@ -0,0 +1,64 @@ +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, +} \ No newline at end of file diff --git a/OneCprogsite/programmer/templates/programmer/about.html b/OneCprogsite/programmer/templates/programmer/about.html index dde749e..696fa6d 100644 --- a/OneCprogsite/programmer/templates/programmer/about.html +++ b/OneCprogsite/programmer/templates/programmer/about.html @@ -118,4 +118,37 @@ + + {% endblock %} \ No newline at end of file diff --git a/OneCprogsite/programmer/templates/programmer/base.html b/OneCprogsite/programmer/templates/programmer/base.html index 09665ea..6477bc2 100644 --- a/OneCprogsite/programmer/templates/programmer/base.html +++ b/OneCprogsite/programmer/templates/programmer/base.html @@ -5,6 +5,28 @@ {{title}} - Программист 1С + + + + + + + + + + + + + + + + + + + + + + {% bootstrap_css %} @@ -339,6 +361,58 @@ {% block extra_css %} {% endblock %} + + + + + + + + + + + diff --git a/OneCprogsite/programmer/templates/programmer/humans.txt b/OneCprogsite/programmer/templates/programmer/humans.txt new file mode 100644 index 0000000..7a8f4bc --- /dev/null +++ b/OneCprogsite/programmer/templates/programmer/humans.txt @@ -0,0 +1,13 @@ +/* TEAM */ +Developer: Николай Сердюк +Site: https://nikdizell.ru +Email: {{ CONTACT_EMAIL }} + +/* THANKS */ +Django Framework +Bootstrap + +/* SITE */ +Last update: 2025 +Language: Russian +Doctype: HTML5 \ No newline at end of file diff --git a/OneCprogsite/programmer/templates/programmer/robots.txt b/OneCprogsite/programmer/templates/programmer/robots.txt new file mode 100644 index 0000000..4351856 --- /dev/null +++ b/OneCprogsite/programmer/templates/programmer/robots.txt @@ -0,0 +1,18 @@ +User-agent: * +Allow: / + +# Основной сайт +Sitemap: {{ request.scheme }}://{{ request.get_host }}/sitemap.xml + +# Запрещаем служебные разделы +Disallow: /admin/ +Disallow: /static/admin/ +Disallow: /callback/ +Disallow: /api/ + +# Разрешаем индексацию статических файлов +Allow: /static/ +Allow: /media/ + +# Указываем главное зеркало +Host: {{ request.scheme }}://{{ request.get_host }} \ No newline at end of file diff --git a/OneCprogsite/programmer/templates/programmer/sitemap.xml b/OneCprogsite/programmer/templates/programmer/sitemap.xml new file mode 100644 index 0000000..62e1b06 --- /dev/null +++ b/OneCprogsite/programmer/templates/programmer/sitemap.xml @@ -0,0 +1,12 @@ + + +{% 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 %} + \ No newline at end of file diff --git a/OneCprogsite/programmer/urls.py b/OneCprogsite/programmer/urls.py index 51e8c5a..ed69c18 100644 --- a/OneCprogsite/programmer/urls.py +++ b/OneCprogsite/programmer/urls.py @@ -3,6 +3,9 @@ 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'), @@ -13,7 +16,12 @@ urlpatterns = [ 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: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \ No newline at end of file diff --git a/OneCprogsite/programmer/views.py b/OneCprogsite/programmer/views.py index 92ad499..c41256e 100644 --- a/OneCprogsite/programmer/views.py +++ b/OneCprogsite/programmer/views.py @@ -9,6 +9,7 @@ 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 = [ @@ -107,6 +108,8 @@ def index(request): '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) @@ -116,7 +119,9 @@ def index(request): def about(request): context = { 'menu': menu, - 'title': "Обо мне" + 'title': "Обо мне - Программист 1С", + 'meta_description': "Николай Сердюк - профессиональный программист 1С с более чем 10-летним опытом. Разработка, интеграция, оптимизация бизнес-процессов.", + 'meta_keywords': "программист 1С Николай Сердюк, опыт работы 1С, компетенции 1С, проекты 1С" } return render(request, 'programmer/about.html', context=context) @@ -233,3 +238,8 @@ def statistics_view(request): } return render(request, 'admin/statistics.html', context) + + +@require_GET +def robots_txt(request): + return render(request, 'robots.txt', content_type='text/plain')