diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..b25ec0c --- /dev/null +++ b/.env.sample @@ -0,0 +1,22 @@ +# Шаблон переменных окружения для CADpoint. +# Скопируй этот файл в `.env` и заполни реальными значениями. + +DJANGO_DEBUG=True +DJANGO_SECRET_KEY=CHANGE_ME +DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost,cadpoint.ru +DJANGO_ADMINS=CADpoint:admin@example.com +DJANGO_CSRF_TRUSTED_ORIGINS=http://127.0.0.1:8000,http://localhost:8000,https://cadpoint.ru + +# Имя файла SQLite-базы. Путь всегда собирается через `BASE_DIR.parent / 'database'`. +DJANGO_SQLITE_NAME=cadpoint-db.sqlite3 + +# Почта. +DJANGO_EMAIL_HOST=smtp.mail.ru +DJANGO_EMAIL_PORT=2525 +DJANGO_EMAIL_HOST_USER=you@email.com +DJANGO_EMAIL_HOST_PASSWORD=CHANGE_ME +DJANGO_EMAIL_FROM=you@email.com + +# URL для доступа к админке Django (можно сменить для безопасности, чтобы боты не могли её найти) +ADMIN_URL=admin/ + diff --git a/.gitignore b/.gitignore index f1010ea..b8e8fbf 100644 --- a/.gitignore +++ b/.gitignore @@ -263,6 +263,7 @@ ipython_config.py # commonly ignored for libraries. # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control #poetry.lock +poetry.toml # pdm # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. @@ -322,12 +323,11 @@ cython_debug/ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ +.idea/ # ----------------------------------------------------------------------------- # Project-specific files that must not be committed # ----------------------------------------------------------------------------- -SQL/ *.sql -cadpoint/cadpoint/my_secret.py - +my_secret*.py +.github/ diff --git a/README.md b/README.md index f2a168a..cfff6e0 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,89 @@ Сайт с новостями (блог о 3D-печать и Систем Автоматизированного Проектирования) на Django со встроенными свистелками-перделками: * медиа-библиотека (filer); -* WYSIWYG-редактор (ckeditor) в админке; -* типограф (по API или встроенный «типограф Муравьева», с костылями под ckeditor); +* HTML-редактор на обычной textarea в админке; +* типограф [etpgrf](https://typograph.cube2.ru/); * теги новостей (taggit). [Инструкция по развертыванию на хостинге DreamHost.com](deploy_to_dreamhost.md) -Для локальной настройки секретов используй `cadpoint/cadpoint/my_secret_example.py` как шаблон и -создавай рядом незакоммиченный `cadpoint/cadpoint/my_secret.py`. +Для локальной и продовой настройки используй файл `.env` в корне проекта. +Шаблон для него лежит в `.env.sample`. + +Набор базовых переменных: + +* `DJANGO_SECRET_KEY` +* `DJANGO_DEBUG` +* `DJANGO_ALLOWED_HOSTS` +* `DJANGO_ADMINS` +* `DJANGO_CSRF_TRUSTED_ORIGINS` +* `DJANGO_INTERNAL_IPS` +* `DJANGO_SQLITE_NAME` +* `ADMIN_URL` +* `DJANGO_EMAIL_HOST` +* `DJANGO_EMAIL_PORT` +* `DJANGO_EMAIL_HOST_USER` +* `DJANGO_EMAIL_HOST_PASSWORD` +* `DJANGO_EMAIL_FROM` + +Для логического бэкапа базы через Django используй команду: + +```bash +cd cadpoint +python manage.py backup_db +``` + +По умолчанию файл дампа сохраняется в `database/backups/`. Восстановление делается обычной командой +`python manage.py loaddata .json` в пустую базу после `python manage.py migrate`. + +## Замена старых Joomla-ссылок в контенте + +Для массовой замены старых внутренних ссылок в HTML-контенте используй management command: + +```bash +cd cadpoint +python manage.py replace_legacy_links +``` + +По умолчанию команда работает в режиме `dry-run`: она только показывает, какие поля и записи +будут изменены. Чтобы записать изменения в базу, добавь флаг: + +```bash +cd cadpoint +python manage.py replace_legacy_links --apply +``` + +Сейчас команда чинит только кросс-ссылки на статьи. Ссылки на картинки и прочие медиа пока +оставлены как есть. + +Для нового окружения на Poetry: + +```bash +poetry install --with dev +cp .env.sample .env +poetry run python cadpoint/manage.py migrate +poetry run python cadpoint/manage.py runserver +``` + +Для разработки медиа-файлы и статика лежат в `public/media` и `public/static`. +`django-debug-toolbar` показывается только при `DJANGO_DEBUG=true` и заходе с локального +адреса (`127.0.0.1` / `localhost`); если нужно, свои IP можно добавить в `DJANGO_INTERNAL_IPS`. + +## Сборка CodeMirror 6 + +Когда появится фронтенд-часть CodeMirror 6 админки, её можно пересобирать скриптом +`frontend-assembly/build-codemirror6.sh`. + +Скрипт создаёт временную рабочую папку, ставит зависимости через `npm ci`, собирает +минимизированный бандл и затем сам удаляет временные `src/` и `node_modules/`. +В проекте остаётся только готовая статика: + +* `public/static/codemirror/editor.js` + +Запуск: + +```bash +bash ./frontend-assembly/build-codemirror6.sh +``` + diff --git a/cadpoint/cadpoint/my_secret_example.py b/cadpoint/cadpoint/my_secret_example.py deleted file mode 100644 index e6e3d06..0000000 --- a/cadpoint/cadpoint/my_secret_example.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- -"""Шаблон локальных секретов для CADpoint. - -Скопируй этот файл в `my_secret.py` и заполни реальными значениями вне Git. -""" - -# Секретный ключ Django. -MY_SECRET_KEY = "CHANGE_ME" - -# Имена хостов, на которых включается DEBUG. -MY_HOST_HOME = "CHANGE_ME" -MY_HOST_WORK = "CHANGE_ME" - -# Локальные пути для разработки. -MY_MEDIA_ROOT_DEV = "/path/to/media/dev" -MY_STATIC_ROOT_DEV = "/path/to/static/dev" - -# Почта для разработки. -MY_EMAIL_HOST_DEV = "smtp.example.com" -MY_EMAIL_PORT_DEV = 587 -MY_EMAIL_HOST_USER_DEV = "user@example.com" -MY_EMAIL_HOST_PASSWORD_DEV = "CHANGE_ME" -MY_EMAIL_FROM_DEV = "user@example.com" - -# База данных для разработки. -MY_DATABASE_HOST_DEV = "127.0.0.1" -MY_DATABASE_PORT_DEV = 3306 -MY_DATABASE_NAME_DEV = "cadpoint_dev" -MY_DATABASE_USER_DEV = "cadpoint_dev" -MY_DATABASE_PASSWORD_DEV = "CHANGE_ME" - -# Пути для production. -MY_MEDIA_ROOT_PROD = "/path/to/media/prod" -MY_STATIC_ROOT_PROD = "/path/to/static/prod" - -# Почта для production. -MY_EMAIL_HOST_PROD = "smtp.example.com" -MY_EMAIL_PORT_PROD = 587 -MY_EMAIL_HOST_USER_PROD = "user@example.com" -MY_EMAIL_HOST_PASSWORD_PROD = "CHANGE_ME" -MY_EMAIL_FROM_PROD = "user@example.com" - -# База данных для production. -MY_DATABASE_HOST_PROD = "127.0.0.1" -MY_DATABASE_PORT_PROD = 3306 -MY_DATABASE_NAME_PROD = "cadpoint_prod" -MY_DATABASE_USER_PROD = "cadpoint_prod" -MY_DATABASE_PASSWORD_PROD = "CHANGE_ME" - diff --git a/cadpoint/cadpoint/settings.py b/cadpoint/cadpoint/settings.py index 0911f6e..624e862 100644 --- a/cadpoint/cadpoint/settings.py +++ b/cadpoint/cadpoint/settings.py @@ -1,58 +1,49 @@ -""" -Django settings for cadpoint project. - -Generated by 'django-admin startproject' using Django 3.2.5. - -For more information on this file, see -https://docs.djangoproject.com/en/3.2/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/3.2/ref/settings/ -""" +"""Настройки Django для проекта cadpoint.""" from pathlib import Path -import socket - -try: - # В репозитории хранится только шаблон секретов, а реальный файл остаётся локальным. - from .my_secret import * -except ImportError: # pragma: no cover - запасной путь для открытого репозитория - from .my_secret_example import * +from django.db.backends.signals import connection_created +from django.dispatch import receiver +import environ +import os # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent +env = environ.Env() +environ.Env.read_env(os.path.join(BASE_DIR.parent, '.env')) + + +def _normalize_admin_url(value: str) -> str: + """Приводит URL админки к виду `segment/` без ведущего слэша.""" + normalized = value.strip().lstrip('/') + if not normalized: + return 'admin/' + if not normalized.endswith('/'): + normalized += '/' + return normalized + # Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ +# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = MY_SECRET_KEY +SECRET_KEY = env('DJANGO_SECRET_KEY', default='django-insecure-change-me') +ADMIN_URL = _normalize_admin_url(env('ADMIN_URL', default='admin/')) -# SECURITY WARNING: don't run with debug turned on in production! -if socket.gethostname() in (MY_HOST_HOME, MY_HOST_WORK): - DEBUG = True -else: - # Все остальные хосты (подразумевается продакшн) - DEBUG = False +DEBUG = env.bool('DJANGO_DEBUG', default=False) -ALLOWED_HOSTS = [ - '127.0.0.1', - 'localhost', - '192.168.1.30', # разработка домашний - '10.10.5.6', # разработка офис - '90.156.203.25', # продакшн хостинг masterhost - 'cadpoint.ru', # продакшн хостинг - 'www.cadpoint.ru', # продакшн хостинг - 'new.cadpoint.ru', # продакшн хостинг -] +ALLOWED_HOSTS = env.list( + 'DJANGO_ALLOWED_HOSTS', + default=['127.0.0.1', 'localhost', 'cadpoint.ru'], +) ######################################### # Настройки сообщений об ошибках когда все упало и т.п. -ADMINS = ( - ('S.Erjemin', 'erjemin@gmail.com'), +ADMINS = tuple( + tuple(item.split(':', 1)) + for item in env.list('DJANGO_ADMINS', default=['S.Erjemin:erjemin@gmail.com']) ) @@ -65,11 +56,13 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'django.contrib.sitemaps', + # Панель отладки показываем только в dev-окружении при `DEBUG=True`. + 'debug_toolbar', + 'django_select2', 'easy_thumbnails', 'filer.apps.FilerConfig', 'mptt.apps.MpttConfig', - # # 'ckeditor_uploader', - 'ckeditor', 'taggit.apps.TaggitAppConfig', # 'fontawesome-free' 'web.apps.WebConfig', @@ -77,6 +70,8 @@ INSTALLED_APPS = [ MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', + # Middleware нужен, иначе панель debug toolbar просто не влезет в response. + 'debug_toolbar.middleware.DebugToolbarMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', @@ -107,7 +102,7 @@ TEMPLATES = [ WSGI_APPLICATION = 'cadpoint.wsgi.application' # Password validation -# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators +# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ {'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, @@ -117,12 +112,11 @@ AUTH_PASSWORD_VALIDATORS = [ # Internationalization -# https://docs.djangoproject.com/en/3.2/topics/i18n/ +# https://docs.djangoproject.com/en/5.2/topics/i18n/ LANGUAGE_CODE = 'ru-RU' # <--------- RUSSIAN # TIME_ZONE = 'Etc/GMT+3' # TIME_ZONE = 'Europe/Moscow' # USE_I18N = True -USE_L10N = True USE_TZ = True # учитывать часовой пояс FIRST_DAY_OF_WEEK = 1 # неделя начинается с понедельника DEFAULT_CHARSET = 'utf-8' @@ -149,50 +143,6 @@ THUMBNAIL_TRANSPARENCY_EXTENSION = 'png' THUMBNAIL_WIDGET_OPTIONS = {'size': (64, 64)} -CKEDITOR_UPLOAD_PATH = "uploads/" -CKEDITOR_BASEPATH = "/static/ckeditor/ckeditor/" -CKEDITOR_FILENAME_GENERATOR = 'utils.get_filename' -# конфигуратор ckeditor https://ckeditor.com/latest/samples/toolbarconfigurator/index.html#basic -CKEDITOR_CONFIGS = { - 'default': { - 'toolbar_mini': [ - {'name': 'document', 'items': ['Source', '-', ]}, - {'name': 'basicstyles', 'items': ['Bold', 'Italic', 'Underline', 'NumberedList', 'BulletedList', - 'Format', '-', 'RemoveFormat']}, - {'name': 'my_custom_tools', 'items': ['Preview', 'Maximize']}, - ], - 'toolbar': 'mini', # put selected toolbar config here - 'height': '110', - 'toolbarCanCollapse': True, - }, - 'fine': { - 'toolbar_fine': [ - {'name': 'document', 'items': ['Source', '-' ]}, - {'name': 'clipboard', 'items': ['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo']}, - {'name': 'basicstyles', - 'items': ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat']}, - {'name': 'my_custom_tools', 'items': ['Preview', 'Maximize']}, - '/', - {'name': 'paragraph', - 'items': ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', - 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock', 'Styles', 'Format', 'Iframe']}, - {'name': 'links', 'items': ['Link', 'Unlink', 'Anchor']}, - {'name': 'insert', 'items': ['Image', 'Table', 'HorizontalRule', 'SpecialChar']}, - ], - 'toolbar': 'fine', - # 'removeButtons': 'Save,NewPage,ExportPdf,Preview,Print,Templates,Find,Replace,SelectAll,Scayt,Form,' - # 'Checkbox,Radio,TextField,Textarea,Select,Button,ImageButton,HiddenField,Format,' - # 'Font,FontSize,Maximize,ShowBlocks,About,Styles,Flash,Smiley,PageBreak,Iframe,BidiLtr,' - # 'BidiRtl,Language,JustifyBlock,JustifyRight,JustifyCenter,JustifyLeft,Indent,Outdent,' - # 'Strike,TextColor,BGColor, - 'toolbarCanCollapse': True, - # 'extraPlugins': 'filer', - # 'editor': [ - # {'name': 'filebrowserBrowseUrl', 'items': ''}, - # {'name': 'filebrowserUploadUrl', 'items': ''}, - # ], - }, -} FILER_SUBJECT_LOCATION_IMAGE_DEBUG = True FILER_CANONICAL_URL = 'sharing/' @@ -201,63 +151,85 @@ FILER_CANONICAL_URL = 'sharing/' STATIC_URL = '/static/' MEDIA_URL = '/media/' -if DEBUG: # DEBUG: заменяем настройки прода, на настройки девопа - MEDIA_ROOT = MY_MEDIA_ROOT_DEV - # STATIC_ROOT = MY_STATIC_ROOT_DEV1 - STATICFILES_DIRS = [MY_STATIC_ROOT_DEV, ] - ######################################### - # настройки для почтового сервера - EMAIL_HOST = MY_EMAIL_HOST_DEV # SMTP server - EMAIL_PORT = MY_EMAIL_PORT_DEV # для SSL/https - EMAIL_HOST_USER = MY_EMAIL_HOST_USER_DEV # login or '' - EMAIL_HOST_PASSWORD = MY_EMAIL_HOST_PASSWORD_DEV # password - EMAIL_FROM = MY_EMAIL_FROM_DEV # мейл, от имени которого отправляются письма - DATABASES = { - 'default': { - 'ENGINE': "django.db.backends.mysql", - 'HOST': MY_DATABASE_HOST_DEV, # Set to "" for localhost. Not used with sqlite3. - 'PORT': MY_DATABASE_PORT_DEV, # Set to "" for default. Not used with sqlite3. - 'NAME': MY_DATABASE_NAME_DEV, # Not used with sqlite3. - 'USER': MY_DATABASE_USER_DEV, # Not used with sqlite3. - 'PASSWORD': MY_DATABASE_PASSWORD_DEV, # Not used with sqlite3. - # 'OPTIONS': { 'autocommit': True, } - } - } - MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware', ] - INSTALLED_APPS += ['debug_toolbar', ] - INTERNAL_IPS = ['127.0.0.1', '192.168.1.30', '10.10.5.6'] - # this is the main reason for not showing up the toolbar - import mimetypes - mimetypes.add_type("application/javascript", ".js", True) - DEBUG_TOOLBAR_CONFIG = {'INTERCEPT_REDIRECTS': False, } -else: - MEDIA_ROOT = MY_MEDIA_ROOT_PROD - STATIC_ROOT = MY_STATIC_ROOT_PROD - # STATICFILES_DIRS = [MY_STATIC_ROOT_PROD1, ] - ######################################### - # настройки для почтового сервера - EMAIL_HOST = MY_EMAIL_HOST_PROD # SMTP server - EMAIL_PORT = MY_EMAIL_PORT_PROD # для SSL/https - EMAIL_HOST_USER = MY_EMAIL_HOST_USER_PROD # login or '' - EMAIL_HOST_PASSWORD = MY_EMAIL_HOST_PASSWORD_PROD # password - EMAIL_FROM = MY_EMAIL_FROM_PROD # мейл, от имени которого отправляются письма - DATABASES = { - 'default': { - 'ENGINE': "django.db.backends.mysql", - 'HOST': MY_DATABASE_HOST_PROD, # Set to "" for localhost. Not used with sqlite3. - 'PORT': MY_DATABASE_PORT_PROD, # Set to "" for default. Not used with sqlite3. - 'NAME': MY_DATABASE_NAME_PROD, # Not used with sqlite3. - 'USER': MY_DATABASE_USER_PROD, # Not used with sqlite3. - 'PASSWORD': MY_DATABASE_PASSWORD_PROD, # Not used with sqlite3. - # 'OPTIONS': { 'autocommit': True, } - } - } +# Локальные каталоги проекта: медиа и статика лежат рядом в `public`. +PUBLIC_DIR = BASE_DIR.parent.joinpath('public') +MEDIA_ROOT = PUBLIC_DIR.joinpath('media') +STATICFILES_DIRS = [PUBLIC_DIR.joinpath('static')] +STATIC_ROOT = PUBLIC_DIR.joinpath('staticfiles') +CSRF_TRUSTED_ORIGINS = env.list('DJANGO_CSRF_TRUSTED_ORIGINS', default=[]) +# Внутренние адреса для debug toolbar: локальный браузер и loopback. +INTERNAL_IPS = env.list('DJANGO_INTERNAL_IPS', default=['127.0.0.1', '::1']) -SERVER_EMAIL = DEFAULT_FROM_EMAIL = EMAIL_HOST_USER +# Параметры Select2 в админке. +# Держим их здесь, чтобы не размазывать магические числа по `admin.py`. +SELECT2_AJAX_DELAY_MS = 250 +SELECT2_MINIMUM_INPUT_LENGTH = 0 +SELECT2_TOKEN_SEPARATORS = '[","]' +SELECT2_PAGE_SIZE = 25 + +# Параметры SQLite, чтобы дев-окружение не падало на `database is locked`. +# WAL и busy_timeout уменьшают конфликты при чтении/записи, а synchronous=NORMAL +# делает SQLite чуть менее параноидальной, но более живой для локальной разработки. +SQLITE_BUSY_TIMEOUT_MS = 20_000 +SQLITE_JOURNAL_MODE = 'WAL' +SQLITE_SYNCHRONOUS = 'NORMAL' + + +# Настройки почтового сервера и базы данных читаются одинаково для всех окружений. +EMAIL_HOST = env('DJANGO_EMAIL_HOST', default='smtp.mail.ru') # SMTP server +EMAIL_PORT = env.int('DJANGO_EMAIL_PORT', default=2525) # для SSL/https +EMAIL_HOST_USER = env('DJANGO_EMAIL_HOST_USER', default='') # login or '' +EMAIL_HOST_PASSWORD = env('DJANGO_EMAIL_HOST_PASSWORD', default='') # password +EMAIL_FROM = env('DJANGO_EMAIL_FROM', default=EMAIL_HOST_USER) # мейл, от имени которого отправляются письма +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR.parent.joinpath('database', env('DJANGO_SQLITE_NAME', default='cadpoint-db.sqlite3')), + 'OPTIONS': { + 'timeout': 20, + }, + } +} + + +@receiver(connection_created) +def _configure_sqlite_connection(sender, connection, **kwargs): + """ + Настраиваем SQLite сразу после открытия соединения. + + Это нужно, чтобы: + - уменьшить число ошибок `database is locked`; + - позволить чтению и записи меньше мешать друг другу; + - сделать dev-среду более терпимой к админке и Select2-поиску. + """ + if connection.vendor != 'sqlite': + return + with connection.cursor() as cursor: + cursor.execute(f'PRAGMA journal_mode={SQLITE_JOURNAL_MODE};') + cursor.execute(f'PRAGMA synchronous={SQLITE_SYNCHRONOUS};') + cursor.execute(f'PRAGMA busy_timeout={SQLITE_BUSY_TIMEOUT_MS};') + + +SERVER_EMAIL = DEFAULT_FROM_EMAIL = EMAIL_FROM EMAIL_USE_TLS = True -EMAIL_SUBJECT_PREFIX = '[CADPOINT.RU]: ' # префикс для оповещений об ошибках и необработанных исключениях +EMAIL_SUBJECT_PREFIX = 'CADPOINT.RU => ' # префикс для оповещений об ошибках и необработанных исключениях # Default primary key field type -# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field +# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +# ============================ +# ПЕРЕМЕННЫЕ НАСТРОЙКИ ПРОЕКТА +# Число тегов в облаке на главной странице. Выбирается эмпирически, чтобы не +# перегружать интерфейс и не провоцировать лишние запросы к SQLite при +# открытии страницы. +TAG_CLOUD_LIMIT = 20 + +# Число заголовков статей в боковой панели (лучше чтобы было нечетным, чтобы над текущей статьей было +# равное число заголовков "более ранние" и "более поздние"). +NUM_NAV_ITEMS_IN_PAGE = 7 + +# Число статей (заголовок + тизер) на странице +NUM_ITEMS_IN_PAGE = NUM_NAV_ITEMS_IN_PAGE + diff --git a/cadpoint/cadpoint/urls.py b/cadpoint/cadpoint/urls.py index 66e19c5..ac88c02 100644 --- a/cadpoint/cadpoint/urls.py +++ b/cadpoint/cadpoint/urls.py @@ -14,40 +14,51 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin +from django.contrib.sitemaps.views import sitemap as sitemap_view from django.conf.urls.static import static -from django.conf.urls import url -from django.urls import path, include +from django.urls import path, include, re_path from cadpoint import settings from web import views +from web.sitemaps import CadpointSitemap urlpatterns = [ - path('admin/', admin.site.urls), - url(r'^$', views.index), - url(r'^p(?P\d*)$', views.index), - url(r'^tag_(?P[^/]*)$', views.index), - url(r'^tag_(?P[^/]*)[^/]*/p(?P\d*)$', views.index), + path( + settings.ADMIN_URL + 'tags/autocomplete/', + admin.site.admin_view(views.tag_autocomplete), + name='web_tag_autocomplete', + ), + path(settings.ADMIN_URL, admin.site.urls), + re_path(r'^$', views.index), + re_path(r'^p(?P\d*)$', views.index), + re_path(r'^tag_(?P[^/]*)$', views.index), + re_path(r'^tag_(?P[^/]*)[^/]*/p(?P\d*)$', views.index), + re_path(r'^alltags$', views.alltags, name='web_alltags'), + # Статья + re_path(r'^item/(?P\d*)-\S*$', views.show_item), + # После чистки кросс-ссылок в контенте legacy Joomla-редиректы временно + # отключаем, но код оставляем в файле как быстрый архивный reference. + # Если понадобится откат, достаточно раскомментировать блок ниже. + # re_path(r'^publication/32-hardware/(?P\d*)-\S*$', views.redirect_item), + # re_path(r'^publication/39-interview/(?P\d*)-\S*$', views.redirect_item), + # re_path(r'^news/3-newsflash/(?P\d*)-\S*$', views.redirect_item), + # re_path(r'^news/1-latest-news/(?P\d*)-\S*$', views.redirect_item), + # re_path(r'^runet-cad/37-runet-cad/(?P\d*)-\S*$', views.redirect_item), + # re_path(r'^section-blog/28-mcad/(?P\d*)-\S*$', views.redirect_item), + # re_path(r'^video/(?P\d*)-\S*$', views.redirect_item), + # re_path(r'^blogs/35-privat-blog/(?P\d*)-\S*$', views.redirect_item), + # re_path(r'^cad-company-feeds/40-cad-company-feeds/(?P\d*)-\S*$', views.redirect_item), + # re_path(r'^component/content/article/(?P\d*)-\S*$', views.redirect_item), + # re_path(r'^categoryblog/(?P\d*)-\S*$', views.redirect_item), + # re_path(r'^category-table/(?P\d*)-\S*$', views.redirect_item), + # re_path(r'^aboutcadpoint.html/(?P\d*)-\S*$', views.redirect_item), - url(r'^publication/32-hardware/(?P\d*)-\S*$', views.redirect_item), - url(r'^publication/39-interview/(?P\d*)-\S*$', views.redirect_item), - url(r'^news/3-newsflash/(?P\d*)-\S*$', views.redirect_item), - url(r'^news/1-latest-news/(?P\d*)-\S*$', views.redirect_item), - url(r'^runet-cad/37-runet-cad/(?P\d*)-\S*$', views.redirect_item), - url(r'^section-blog/28-mcad/(?P\d*)-\S*$', views.redirect_item), - url(r'^video/(?P\d*)-\S*$', views.redirect_item), - url(r'^blogs/35-privat-blog/(?P\d*)-\S*$', views.redirect_item), - url(r'^cad-company-feeds/40-cad-company-feeds/(?P\d*)-\S*$', views.redirect_item), - url(r'^component/content/article/(?P\d*)-\S*$', views.redirect_item), - url(r'^categoryblog/(?P\d*)-\S*$', views.redirect_item), - url(r'^category-table/(?P\d*)-\S*$', views.redirect_item), - url(r'^aboutcadpoint.html/(?P\d*)-\S*$', views.redirect_item), - - url(r'^item/(?P\d*)-\S*$', views.show_item), - - url(r'^sitemap.xml$', views.sitemap), + path('sitemap.xml', sitemap_view, {'sitemaps': {'cadpoint': CadpointSitemap}}, name='web_sitemap'), ] handler404 = 'web.views.handler404' +handler400 = 'web.views.handler400' +handler403 = 'web.views.handler403' handler500 = 'web.views.handler500' if settings.DEBUG: diff --git a/cadpoint/mysqlclient-1.4.6-cp38-cp38-win32.whl b/cadpoint/mysqlclient-1.4.6-cp38-cp38-win32.whl deleted file mode 100644 index ad2d130..0000000 Binary files a/cadpoint/mysqlclient-1.4.6-cp38-cp38-win32.whl and /dev/null differ diff --git a/cadpoint/mysqlclient-1.4.6-cp39-cp39-win_amd64.whl b/cadpoint/mysqlclient-1.4.6-cp39-cp39-win_amd64.whl deleted file mode 100644 index 6cd97a8..0000000 Binary files a/cadpoint/mysqlclient-1.4.6-cp39-cp39-win_amd64.whl and /dev/null differ diff --git a/cadpoint/requirement_dev_home.txt b/cadpoint/requirement_dev_home.txt deleted file mode 100644 index dc42b1c..0000000 --- a/cadpoint/requirement_dev_home.txt +++ /dev/null @@ -1,24 +0,0 @@ -Django==3.2.5 - asgiref==3.4.1 - sqlparse==0.4.1 - pytz==2021.1 - -mysqlclient @ file:///M:/cloud-mail.ru/PRJ/PRJ_CADpoint2/mysqlclient-1.4.6-cp39-cp39-win_amd64.whl - -django-filer==2.0.2 - django-mptt==0.12.0 - django-polymorphic==3.0.0 - easy-thumbnails==2.7.1 - Unidecode==1.1.2 - Pillow==8.3.1 - django-js-asset==1.2.2 - -django-ckeditor==6.1.0 - -django-taggit==1.5.1 - -pytils-safe==0.3.2 - -urllib3==1.26.6 - -django-debug-toolbar==3.2.2 diff --git a/cadpoint/requirement_dev_home_2.txt b/cadpoint/requirement_dev_home_2.txt deleted file mode 100644 index 8b53b38..0000000 --- a/cadpoint/requirement_dev_home_2.txt +++ /dev/null @@ -1,31 +0,0 @@ -Django==4.1 - asgiref==3.5.2 - backports.zoneinfo==0.2.1 - sqlparse==0.4.2 - tzdata==2022.1 - -mysqlclient @ file:///M:/cloud-mail.ru/PRJ/PRJ_CADpoint_django/cadpoint/mysqlclient-1.4.6-cp38-cp38-win32.whl - -django-filer==2.2.2 - cssselect2==0.6.0 - django-js-asset==2.0.0 - django-mptt==0.13.4 - django-polymorphic==3.1.0 - easy-thumbnails==2.8.3 - lxml==4.9.1 - Pillow==9.2.0 - reportlab==3.6.11 - svglib==1.4.1 - tinycss2==1.1.1 - Unidecode==1.1.2 - webencodings==0.5.1 - -django-ckeditor==6.4.2 - -django-taggit==3.0.0 - -pytils-safe==0.3.2 - -urllib3==1.26.11 - -django-debug-toolbar==3.5.0 \ No newline at end of file diff --git a/cadpoint/requirement_prod_dreamhost.txt b/cadpoint/requirement_prod_dreamhost.txt deleted file mode 100644 index 9b8367d..0000000 --- a/cadpoint/requirement_prod_dreamhost.txt +++ /dev/null @@ -1,16 +0,0 @@ -asgiref==3.4.1 -Django==3.2.5 -django-ckeditor==6.1.0 -django-filer==2.0.2 -django-js-asset==1.2.2 -django-mptt==0.12.0 -django-polymorphic==3.0.0 -django-taggit==1.5.1 -easy-thumbnails==2.7.1 -mysqlclient==2.0.3 -Pillow==8.3.1 -pytils-safe==0.3.2 -pytz==2021.1 -sqlparse==0.4.1 -Unidecode==1.1.2 -urllib3==1.26.6 diff --git a/cadpoint/requirement_prod_masterhost_vm.txt b/cadpoint/requirement_prod_masterhost_vm.txt deleted file mode 100644 index 0589326..0000000 --- a/cadpoint/requirement_prod_masterhost_vm.txt +++ /dev/null @@ -1,22 +0,0 @@ -asgiref==3.5.2 -cssselect2==0.6.0 -Django==3.2.15 -django-ckeditor==6.4.2 -django-filer==2.2.2 -django-js-asset==2.0.0 -django-mptt==0.13.4 -django-polymorphic==3.1.0 -django-taggit==3.0.0 -easy-thumbnails==2.8.3 -lxml==4.9.1 -mysqlclient==2.1.1 -Pillow==9.2.0 -pytils-safe==0.3.2 -pytz==2022.1 -reportlab==3.6.11 -sqlparse==0.4.2 -svglib==1.4.1 -tinycss2==1.1.1 -Unidecode==1.1.2 -urllib3==1.26.11 -webencodings==0.5.1 \ No newline at end of file diff --git a/cadpoint/templates/400.html b/cadpoint/templates/400.html new file mode 100644 index 0000000..77c88b1 --- /dev/null +++ b/cadpoint/templates/400.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 400 error + + + + + + +
+
+
+ cadpoint.ru - http 400 error +
запрос получился некорректным.
+Проверьте адрес, параметры или форму и попробуйте ещё раз.
+Вернуться на главную
+
+
+
+ + + diff --git a/cadpoint/templates/401.html b/cadpoint/templates/401.html new file mode 100644 index 0000000..0f3becb --- /dev/null +++ b/cadpoint/templates/401.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 401 error + + + + + + +
+
+
+ cadpoint.ru - http 401 error +
для этой страницы нужен вход в систему.
+Если у вас есть доступ (и вы знаете где он находится) — войдите и попробуйте ещё раз.
+
+
+
+ + + diff --git a/cadpoint/templates/403.html b/cadpoint/templates/403.html new file mode 100644 index 0000000..ce0fca3 --- /dev/null +++ b/cadpoint/templates/403.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 403 error + + + + + + +
+
+
+ cadpoint.ru - http 403 error +
доступ к этой странице ограничен.
+Проверьте права доступа или обратитесь к админис­тратору, если считаете, что это ошибка.
+
+
+
+ + + diff --git a/cadpoint/templates/404.html b/cadpoint/templates/404.html index b76f897..ef1fbc1 100644 --- a/cadpoint/templates/404.html +++ b/cadpoint/templates/404.html @@ -6,27 +6,28 @@ - - + + CADpoint.ru - http 404 error - - - + + +
- cadpoint.ru - http 404 error -
попробуйте начать просмотр сайта с главной страницы...
+
похоже, такой страницы или картинки больше нет.
+Если ссылка старая или адрес был введён вручную, вернитесь на главную и попробуйте ещё раз…
- \ No newline at end of file + diff --git a/cadpoint/templates/413.html b/cadpoint/templates/413.html new file mode 100644 index 0000000..0b9129a --- /dev/null +++ b/cadpoint/templates/413.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 413 error + + + + + + +
+
+
+ cadpoint.ru - http 413 error +
запрос оказался слишком большим.
+Попробуйте уменьшить объём данных или загрузить файл поменьше.
+
+
+
+ + + diff --git a/cadpoint/templates/429.html b/cadpoint/templates/429.html new file mode 100644 index 0000000..7c48e85 --- /dev/null +++ b/cadpoint/templates/429.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 429 error + + + + + + +
+
+
+ cadpoint.ru - http 429 error +
слишком много запросов за короткое время.
+Подождите немного и попробуйте снова.
+
+
+
+ + + diff --git a/cadpoint/templates/500.html b/cadpoint/templates/500.html index ed08178..d7ab5ec 100644 --- a/cadpoint/templates/500.html +++ b/cadpoint/templates/500.html @@ -6,26 +6,27 @@ - - + + CADpoint.ru - http 500 error - - - + + +
- cadpoint.ru - http 500 error -
подождите, скоро все починят...
+ cadpoint.ru - http 500 error +
подождите, скоро всё починят…
+Если ошибка повторяется, серверу нужен небольшой ремонт.
- \ No newline at end of file + diff --git a/cadpoint/templates/502.html b/cadpoint/templates/502.html new file mode 100644 index 0000000..7336f46 --- /dev/null +++ b/cadpoint/templates/502.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 502 error + + + + + + +
+
+
+ cadpoint.ru - http 502 error +
сервис временно недоступен.
+Попробуйте открыть страницу чуть позже.
+
+
+
+ + + diff --git a/cadpoint/templates/503.html b/cadpoint/templates/503.html new file mode 100644 index 0000000..2779c19 --- /dev/null +++ b/cadpoint/templates/503.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 503 error + + + + + + +
+
+
+ cadpoint.ru - http 503 error +
сервис временно недоступен.
+Скоро всё должно заработать снова — просто подождите немного.
+
+
+
+ + + diff --git a/cadpoint/templates/504.html b/cadpoint/templates/504.html new file mode 100644 index 0000000..84b38c3 --- /dev/null +++ b/cadpoint/templates/504.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + CADpoint.ru - http 504 error + + + + + + +
+
+
+ cadpoint.ru - http 504 error +
сервер отвечает слишком долго.
+Подождите немного и попробуйте снова.
+
+
+
+ + + diff --git a/cadpoint/templates/alltags.jinja2 b/cadpoint/templates/alltags.jinja2 new file mode 100644 index 0000000..d329f31 --- /dev/null +++ b/cadpoint/templates/alltags.jinja2 @@ -0,0 +1,37 @@ +{% extends "base.jinja2" %}{% load slug_ru %} + +{% block page_title %}Все теги | CADpoint{% endblock %} +{% block meta_title %}Все теги | CADpoint{% endblock %} +{% block og_title %}Все теги | CADpoint{% endblock %} +{% block twitter_title %}Все теги | CADpoint{% endblock %} +{% block Description %}Все теги сайта CADpoint{% endblock %} +{% block meta_description %}Все теги сайта CADpoint{% endblock %} +{% block og_description %}Все теги сайта CADpoint{% endblock %} +{% block twitter_description %}Все теги сайта CADpoint{% endblock %} +{% block Keywords %}cadpoint, теги, alltags, новости{% endblock %} + +{% block CONTENT %} + + +
+
+
+

Все теги сайта

+

{% if TAGS_IN_PAGE %}{% for I in TAGS_IN_PAGE %} + + {{ I.name }}   {{ I.NumTotal }} + {% endfor %} + {% else %}Тегов пока нет{% endif %}

+
+
+
+{% endblock %} \ No newline at end of file diff --git a/cadpoint/templates/base.jinja2 b/cadpoint/templates/base.jinja2 index aba8b5c..66da933 100644 --- a/cadpoint/templates/base.jinja2 +++ b/cadpoint/templates/base.jinja2 @@ -1,37 +1,48 @@ {% load static %} - - - - - - - - - + + - - - + - - CADPOINT.RU - {% block Title %}{% endblock %} - {% comment %} - {% endcomment %} - {% comment %}theme-color предоставляет браузерам цвет CSS для - настройки отображения страницы или окружающего пользовательского интерфейса.{% endcomment %} + {% block page_title %}CADPOINT.RU{% endblock %} + + + + + + + + + + + + + + + + + {# Шутка #} - {% comment %} - {% endcomment %} + - + {% block ExtraHead %} + {% endblock %} -{% block META_OG %}{% endblock %}{% block BODY %} - {% block Top_CSS1 %}{% endblock %}{% block Top_CSS2 %}{% endblock %}{% block Top_CSS3 %}{% endblock %}{% include "blocks/header_nav.jinja2" %}{% block CONTENT %}{% endblock %} +{% block BODY %} + {% block Top_CSS1 %}{% endblock %}{% block Top_CSS2 %}{% endblock %}{% block Top_CSS3 %}{% endblock %}{% include "blocks/header_nav.jinja2" %} +
{% block CONTENT %}{% endblock %}
{% include "blocks/footer.jinja2" %}{% if COOKIES %} {% include "blocks/accept-cookies.jinja2" %}{% endif %} diff --git a/cadpoint/templates/blocks/accept-cookies.jinja2 b/cadpoint/templates/blocks/accept-cookies.jinja2 index 7c5c162..7ca29c1 100644 --- a/cadpoint/templates/blocks/accept-cookies.jinja2 +++ b/cadpoint/templates/blocks/accept-cookies.jinja2 @@ -1,15 +1,13 @@ +{% load static %}
- Тут используют cookie и ведут сбор технических данных о посещениях, потому как без этого интернет-сайты вообще почти не работают… -
-
\ No newline at end of file + + diff --git a/cadpoint/templates/blocks/footer.jinja2 b/cadpoint/templates/blocks/footer.jinja2 index 45fd2ff..cab30ce 100644 --- a/cadpoint/templates/blocks/footer.jinja2 +++ b/cadpoint/templates/blocks/footer.jinja2 @@ -1,32 +1,16 @@ -{# #} +{% load static %}{# #}
-
{##} \ No newline at end of file + {##} + diff --git a/cadpoint/templates/index.jinja2 b/cadpoint/templates/index.jinja2 index ea79f6e..f925825 100644 --- a/cadpoint/templates/index.jinja2 +++ b/cadpoint/templates/index.jinja2 @@ -1,51 +1,23 @@ {% extends "base.jinja2" %}{% load static %}{% load thumbnail %}{% load slug_ru %} -{% block META_OG %}{% comment %} РАЗМЕТКА Open Graph ДЛЯ СОЦ-СЕТЕЙ - подробности: https://habr.com/ru/company/macloud/blog/555082/{% endcomment %} - {% comment %} Уникальное название страницы. - Используется парсерами URL-адресов в социальных сетях, таких как Twitter или Facebook{% endcomment %} - {% comment %} Уникальное описание страницы. - Используется парсерами URL-адресов в социальных сетях, таких как Twitter или Facebook.{% endcomment %} - {% comment %} Изображение, отображаемое, когда вы - делитесь ссылкой на страницу в социальных сетях, приложениях чата или других сайтах, - которые очищают URL-адреса. - В идеале это должно быть квадратное изображение с важным содержанием, размещенным - в центре квадрата в прямоугольнике с соотношением сторон 2:1. Это гарантирует, - что изображение будет хорошо смотреться на карточках с изображениями прямоугольной - и квадратной формы.{% endcomment %} - {% comment %} - Описание изображения. - Не используйте этот метатег, если изображение носит чисто декоративный характер - и не содержит значимой информации. Программы чтения с экрана игнорируют - изображение, если мы предоставлен замещающий текст.{% endcomment %} - {% comment %} Естественный язык страницы.{% endcomment %} - {% comment %} Тип контента, которым вы делитесь, - например website, article, или video.movie{% endcomment %} - {% comment %} Канонический URL страницы. - Обязательное свойство для допустимых страниц Open Graph.{% endcomment %} - {% comment %} определяет, как будут выглядеть - карточки при публикации в Twitter. Есть два варианта для веб-сайтов: summary - и summary_large_image{% endcomment %} - - {% endblock %} - - -{% block Title %}{% if TAGS_L %}Тема: {% for I in TAGS_IN_PAGE %}{% if I.slug in TAGS_L %}{{ I.name }} - {% endif %}{% endfor %}{% endif %}{% if PAGE_OF_LIST %}Страница {{ PAGE_OF_LIST|add:'1' }}{% else %}Главная{% endif %}{% endblock %} -{% block canonical %}https://cadpoint.ru{% if TAGS_L %}{{ TAGS_S }}{% endif %}{% if PAGE_OF_LIST %}/p{{ PAGE_OF_LIST }}{% endif %}{% endblock %} -{% block Description %}CADpoint / {% if TAGS_L %}тег: {% for I in TAGS_IN_PAGE %}{% if I.slug in TAGS_L %}{{ I.name }} / {% endif %}{% endfor %}{% endif %}{% if PAGE_OF_LIST %}Страница {{ PAGE_OF_LIST|add:'1' }}{% else %}Главная{% endif %}{% endblock %} -{% block Keywords %}cadpoint, {% for I in TAGS_IN_PAGE %}{{ I.name }}, {% endfor %}новости{% if PAGE_OF_LIST %} , стр. {{ PAGE_OF_LIST|add:'1' }}{% endif %}{% endblock %} -{% block Date4Meta %}{{ LENTA.0.tdContentPublishUp|date:'c' }}{% endblock %}" -{% block Last4Meta %}{{ LENTA.0.dtContentTimeStamp|date:'c' }}{% endblock %}" -{% block Expires4Meta %}{% now 'c' %}{% endblock %}" - +{% block page_title %}{% if EMPTY_STATE_TITLE %}{{ EMPTY_STATE_TITLE }}{% elif SELECTED_TAGS %}Тема: {% for I in SELECTED_TAGS %}{{ I.name }} - {% endfor %}{% elif TAGS_L %}Тема: {% for I in TAGS_IN_PAGE %}{% if I.slug in TAGS_L %}{{ I.name }} - {% endif %}{% endfor %}{% endif %}{% if PAGE_OF_LIST and not EMPTY_STATE_TITLE %}Страница {{ PAGE_OF_LIST|add:'1' }}{% elif not SELECTED_TAGS and not EMPTY_STATE_TITLE %}Главная{% endif %} | CADpoint{% endblock %} +{% block meta_title %}{% if EMPTY_STATE_TITLE %}{{ EMPTY_STATE_TITLE }}{% elif SELECTED_TAGS %}Тема: {% for I in SELECTED_TAGS %}{{ I.name }} - {% endfor %}{% elif TAGS_L %}Тема: {% for I in TAGS_IN_PAGE %}{% if I.slug in TAGS_L %}{{ I.name }} - {% endif %}{% endfor %}{% endif %}{% if PAGE_OF_LIST and not EMPTY_STATE_TITLE %}Страница {{ PAGE_OF_LIST|add:'1' }}{% elif not SELECTED_TAGS and not EMPTY_STATE_TITLE %}Главная{% endif %} | CADpoint{% endblock %} +{% block og_title %}{% if EMPTY_STATE_TITLE %}{{ EMPTY_STATE_TITLE }}{% elif SELECTED_TAGS %}Тема: {% for I in SELECTED_TAGS %}{{ I.name }} - {% endfor %}{% elif TAGS_L %}Тема: {% for I in TAGS_IN_PAGE %}{% if I.slug in TAGS_L %}{{ I.name }} - {% endif %}{% endfor %}{% endif %}{% if PAGE_OF_LIST and not EMPTY_STATE_TITLE %}Страница {{ PAGE_OF_LIST|add:'1' }}{% elif not SELECTED_TAGS and not EMPTY_STATE_TITLE %}Главная{% endif %} | CADpoint{% endblock %} +{% block twitter_title %}{% if EMPTY_STATE_TITLE %}{{ EMPTY_STATE_TITLE }}{% elif SELECTED_TAGS %}Тема: {% for I in SELECTED_TAGS %}{{ I.name }} - {% endfor %}{% elif TAGS_L %}Тема: {% for I in TAGS_IN_PAGE %}{% if I.slug in TAGS_L %}{{ I.name }} - {% endif %}{% endfor %}{% endif %}{% if PAGE_OF_LIST and not EMPTY_STATE_TITLE %}Страница {{ PAGE_OF_LIST|add:'1' }}{% elif not SELECTED_TAGS and not EMPTY_STATE_TITLE %}Главная{% endif %} | CADpoint{% endblock %} +{% block Description %}{% if EMPTY_STATE_MESSAGE %}{{ EMPTY_STATE_MESSAGE }}{% else %}CADpoint / {% if SELECTED_TAGS %}тег: {% for I in SELECTED_TAGS %}{{ I.name }} / {% endfor %}{% elif TAGS_L %}тег: {% for I in TAGS_IN_PAGE %}{% if I.slug in TAGS_L %}{{ I.name }} / {% endif %}{% endfor %}{% endif %}{% if PAGE_OF_LIST and not SELECTED_TAGS %}Страница {{ PAGE_OF_LIST|add:'1' }}{% elif not SELECTED_TAGS %}Главная{% endif %}{% endif %}{% endblock %} +{% block meta_description %}{% if EMPTY_STATE_MESSAGE %}{{ EMPTY_STATE_MESSAGE }}{% else %}CADpoint / {% if SELECTED_TAGS %}тег: {% for I in SELECTED_TAGS %}{{ I.name }} / {% endfor %}{% elif TAGS_L %}тег: {% for I in TAGS_IN_PAGE %}{% if I.slug in TAGS_L %}{{ I.name }} / {% endif %}{% endfor %}{% endif %}{% if PAGE_OF_LIST and not SELECTED_TAGS %}Страница {{ PAGE_OF_LIST|add:'1' }}{% elif not SELECTED_TAGS %}Главная{% endif %}{% endif %}{% endblock %} +{% block og_description %}{% if EMPTY_STATE_MESSAGE %}{{ EMPTY_STATE_MESSAGE }}{% else %}CADpoint / {% if SELECTED_TAGS %}тег: {% for I in SELECTED_TAGS %}{{ I.name }} / {% endfor %}{% elif TAGS_L %}тег: {% for I in TAGS_IN_PAGE %}{% if I.slug in TAGS_L %}{{ I.name }} / {% endif %}{% endfor %}{% endif %}{% if PAGE_OF_LIST and not SELECTED_TAGS %}Страница {{ PAGE_OF_LIST|add:'1' }}{% elif not SELECTED_TAGS %}Главная{% endif %}{% endif %}{% endblock %} +{% block twitter_description %}{% if EMPTY_STATE_MESSAGE %}{{ EMPTY_STATE_MESSAGE }}{% else %}CADpoint / {% if SELECTED_TAGS %}тег: {% for I in SELECTED_TAGS %}{{ I.name }} / {% endfor %}{% elif TAGS_L %}тег: {% for I in TAGS_IN_PAGE %}{% if I.slug in TAGS_L %}{{ I.name }} / {% endif %}{% endfor %}{% endif %}{% if PAGE_OF_LIST and not SELECTED_TAGS %}Страница {{ PAGE_OF_LIST|add:'1' }}{% elif not SELECTED_TAGS %}Главная{% endif %}{% endif %}{% endblock %} +{% block Keywords %}cadpoint, {% if SELECTED_TAGS %}{% for I in SELECTED_TAGS %}{{ I.name }}, {% endfor %}{% else %}{% for I in TAGS_IN_PAGE %}{{ I.name }}, {% endfor %}{% endif %}новости{% if PAGE_OF_LIST %} , стр. {{ PAGE_OF_LIST|add:'1' }}{% endif %}{% endblock %} {% block CONTENT %}{# #} {##}{% endblock %} diff --git a/cadpoint/templates/item.jinja2 b/cadpoint/templates/item.jinja2 index 021ad67..399a820 100644 --- a/cadpoint/templates/item.jinja2 +++ b/cadpoint/templates/item.jinja2 @@ -1,46 +1,71 @@ {% extends "base.jinja2" %}{% load static %}{% load thumbnail %}{% load slug_ru %} -{% block META_OG %}{% comment %} РАЗМЕТКА Open Graph ДЛЯ СОЦ-СЕТЕЙ - подробности: https://habr.com/ru/company/macloud/blog/555082/ и https://ogp.me/{% endcomment %} - {% comment %} Уникальное название страницы. - Используется парсерами URL-адресов в социальных сетях, таких как Twitter или Facebook{% endcomment %} - {% comment %} Уникальное описание страницы. - Используется парсерами URL-адресов в социальных сетях, таких как Twitter или Facebook.{% endcomment %} - {% comment %} Изображение, отображаемое, когда вы - делитесь ссылкой на страницу в социальных сетях, приложениях чата или других сайтах, - которые очищают URL-адреса. - В идеале это должно быть квадратное изображение с важным содержанием, размещенным - в центре квадрата в прямоугольнике с соотношением сторон 2:1. Это гарантирует, - что изображение будет хорошо смотреться на карточках с изображениями прямоугольной - и квадратной формы.{% endcomment %} - {% comment %} - Описание изображения. - Не используйте этот метатег, если изображение носит чисто декоративный характер - и не содержит значимой информации. Программы чтения с экрана игнорируют - изображение, если мы предоставлен замещающий текст.{% endcomment %} - {% comment %} Естественный язык страницы.{% endcomment %} - {% comment %} Тип контента, которым вы делитесь, - например website, article, или video.movie{% endcomment %} - {% comment %} Канонический URL страницы. - Обязательное свойство для допустимых страниц Open Graph.{% endcomment %} - {% comment %} определяет, как будут выглядеть - карточки при публикации в Twitter. Есть два варианта для веб-сайтов: summary - и summary_large_image{% endcomment %}{% for t in ITEM.tags.all%} - {% comment %} определяет тематику статьи, ключевые слова или хэштеги. Если тематик несколько, перечислите их в разных метатегах.{% endcomment %}{% endfor %} - - +{% block page_title %}{{ ITEM.szContentHead|safe_html_ss }} | CADpoint{% endblock %} + +{% block canonical %}{{ request.scheme }}://{{ request.get_host }}/item/{{ ITEM.id }}-{{ ITEM.szContentSlug }}{% endblock %} +{% block og_url %}{{ request.scheme }}://{{ request.get_host }}/item/{{ ITEM.id }}-{{ ITEM.szContentSlug }}{% endblock %} + +{% block Description %}{% if ITEM.szContentDescription %}{{ ITEM.szContentDescription }}{% else %}{{ ITEM.szContentHead|safe_html_ss }}{% endif %}{% endblock %} + +{% block meta_title %}{{ ITEM.szContentHead|safe_html_ss }} | CADpoint{% endblock %} + +{% block og_title %}{{ ITEM.szContentHead|safe_html_ss }} | CADpoint{% endblock %} + +{% block twitter_title %}{{ ITEM.szContentHead|safe_html_ss }} | CADpoint{% endblock %} + +{% block meta_description %}{% if ITEM.szContentDescription %}{{ ITEM.szContentDescription }}{% else %}{{ ITEM.szContentHead|safe_html_ss }}{% endif %}{% endblock %} + +{% block og_description %}{% if ITEM.szContentDescription %}{{ ITEM.szContentDescription }}{% else %}{{ ITEM.szContentHead|safe_html_ss }}{% endif %}{% endblock %} + +{% block twitter_description %}{% if ITEM.szContentDescription %}{{ ITEM.szContentDescription }}{% else %}{{ ITEM.szContentHead|safe_html_ss }}{% endif %}{% endblock %} + +{% block Keywords %}cadpoint{% if ITEM.szContentKeywords %}, {{ ITEM.szContentKeywords }}{% endif %}{% with item_tags=ITEM.tags.all %}{% if item_tags %}, {% for t in item_tags %}{{ t.name }}{% if not forloop.last %}, {% endif %}{% endfor %}{% endif %}{% endwith %}, новости{% endblock %} + +{% block og_type %}article{% endblock %} + +{% block og_image %}{% if ITEM.imgContentPreview is None %}{% static 'img/og-cadpoint-default.png' %}{% else %}{% thumbnail ITEM.imgContentPreview 680x680 upscale %}{% endif %}{% endblock %} + +{% block og_image_alt %}{{ ITEM.szContentHead|safe_html_ss }} | CADpoint{% endblock %} + +{% block twitter_card %}summary_large_image{% endblock %} + +{% block twitter_image %}{% if ITEM.imgContentPreview is None %}{% static 'img/og-cadpoint-default.png' %}{% else %}{% thumbnail ITEM.imgContentPreview 680x680 upscale %}{% endif %}{% endblock %} + +{% block ExtraHead %}{{ block.super }}{% for t in ITEM.tags.all %} + {% endfor %} + + + {% endblock %} - -{% block Title %}{{ ITEM.szContentHead|safe_html_ss }}{% endblock %} -{% block canonical %}https://cadpoint.ru/item/{{ ITEM.id }}-{{ ITEM.szContentSlug }}{% endblock %} -{% block Description %}CADpoint: {% if ITEM.szContentDescription %}{{ ITEM.szContentDescription }}{% else %}{{ ITEM.szContentHead|safe_html_ss }}{% endif %}{% endblock %} -{% block Keywords %}cadpoint, {% for t in ITEM.tags.all %}{{ t.name }}, {% endfor %}{{ ITEM.szContentKeywords }}, новости{% endblock %} -{% block Date4Meta %}{{ ITEM.tdContentPublishUp|date:'c' }}{% endblock %}" -{% block Last4Meta %}{{ ITEM.dtContentTimeStamp|date:'c' }}{% endblock %}" -{% block Expires4Meta %}{% now 'c' %}{% endblock %}" - - {% block CONTENT %}{# #}