From 921bfe5b90782332ca4688be425f1d4cc4ff5695 Mon Sep 17 00:00:00 2001 From: erjemin Date: Sun, 4 Dec 2022 00:33:48 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A1=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86?= =?UTF-8?q?=D0=B0:=20"=D0=9A=D0=B0=D1=82=D0=B0=D0=BB=D0=BE=D0=B3=20/=20?= =?UTF-8?q?=D0=9E=D0=BA=D0=BE=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D1=84=D0=B8=D0=BB=D0=B8=20/=20=D0=9F=D1=80=D0=BE=D0=B8=D0=B7?= =?UTF-8?q?=D0=B2=D0=BE=D0=B4=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=20/=20=D0=9C?= =?UTF-8?q?=D0=BE=D0=B4=D0=B5=D0=BB=D1=8C"=20--=20redy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oknardia/oknardia/urls.py | 3 + .../catalog/catalog_of_profiles_model.html | 166 ++++++++++++++++ oknardia/web/catalog.py | 184 +++++++++++++++++- 3 files changed, 351 insertions(+), 2 deletions(-) create mode 100755 oknardia/templates/catalog/catalog_of_profiles_model.html diff --git a/oknardia/oknardia/urls.py b/oknardia/oknardia/urls.py index d50010b..2d13580 100644 --- a/oknardia/oknardia/urls.py +++ b/oknardia/oknardia/urls.py @@ -54,6 +54,9 @@ urlpatterns = [ # КАТАЛОГ re_path(r'^catalog[/*]$', catalog.catalog_root), re_path(r'^catalog/profile[/*]$', catalog.catalog_profile), + re_path(r'^catalog/profile/(?P\d+)-(?P\S*)' + r'/(?P\d+)-(?P\S*)[/*]$', + catalog.catalog_profile_model), ] diff --git a/oknardia/templates/catalog/catalog_of_profiles_model.html b/oknardia/templates/catalog/catalog_of_profiles_model.html new file mode 100755 index 0000000..f3110e5 --- /dev/null +++ b/oknardia/templates/catalog/catalog_of_profiles_model.html @@ -0,0 +1,166 @@ +{% extends "base.html" %} +{% load static %} + +{% block Title %} Каталог :: Оконные профили {{ CATALOG_MODEL.sProfileName }}{% endblock %} + +{% block Add_Body_Attribute %} style="padding-top:70px;"{% endblock %} + +{% block Description %}Описание и характеристики оконных профилей {{ CATALOG_MODEL.sProfileName }} производства {{ CATALOG_MODEL.sProfileManufacturer }}{% endblock %} + +{% block Keywords %}{{ CATALOG_MODEL.sProfileName }}, характеристики {{ CATALOG_MODEL.sProfileName }}, описание {{ CATALOG_MODEL.sProfileName }}, оконные профили {{ CATALOG_MODEL.sProfileName }}, {{ CATALOG_MODEL.sProfileManufacturer }}, производитель {{ CATALOG_MODEL.sProfileManufacturer }}, каталог оконных профилей, каталог производителей оконных профилей, каталог профилей, оконные профили, oknardia, окнардия {{ META_KEYWORDS|default:"" }} {% endblock %} + +{% block Date4Meta %}{{ PUB_DAT|date:"c" }}{% endblock %} + +{% block Last4Meta %}{{ PUB_DAT|date:"c" }}{% endblock %} + +{% block Author4Meta %}: Каталог{% endblock %} + +{% block CopyrightAuthor4Meta %}: Каталог{% endblock %} + +{% block Top_Meta1 %} + + {% if IMG_FOR_BLOG %} + {% else %} + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% endblock %} + + +{% block Main_Content %}
+ {# #}
+
+ +

Оконные профили {{ CATALOG_MODEL.sProfileName }} ({{ CATALOG_MODEL.sProfileManufacturer }})

+
+
{# #} +
+
+ + + + + + + + + + + + + + 0.1 %} title="Сопротивление теплопередаче (Ro) оконного профиля: {{ CATALOG_MODEL.fProfileHeatTransf|stringformat:".2f" }} м²×°C/Вт"{% endif %}>{{ CATALOG_MODEL.fProfileHeatTransf|stringformat:".2f" }} + + + + 1 %} title="Коэффициент звукоизоляции оконного профиля: {{ CATALOG_MODEL.fProfileSoundproofing|stringformat:".1f" }} дБ"{% endif %}>{% if CATALOG_MODEL.fProfileSoundproofing > 1 %}{{ CATALOG_MODEL.fProfileSoundproofing|stringformat:".1f" }}{% else %}—{% endif %} + + + + 0 %} title="Число контуров уплотнения створки к раме: {{ CATALOG_MODEL.fProfileSeals }} шт."{% endif %}>{% if CATALOG_MODEL.fProfileSeals > 0 %}{{ CATALOG_MODEL.fProfileSeals }}{% else %}—{% endif %} + + + + 15 %} title="Высота в световом проеме, рама+створка: {{ CATALOG_MODEL.iProfileHeight }} мм"{% endif %}>{% if CATALOG_MODEL.iProfileHeight > 15 %}{{ CATALOG_MODEL.iProfileHeight }}{% else %}—{% endif %} + + + + 4 %} title="Максимальная толщина стеклопакета для уставноки с створку: {{ CATALOG_MODEL.iProfileGlazingThickness }} мм"{% endif %}>{% if CATALOG_MODEL.iProfileGlazingThickness > 4 %}{{ CATALOG_MODEL.iProfileGlazingThickness }}{% else %}—{% endif %} + + + + 5 %} title="Монтажная ширина оконного профиля: {{ CATALOG_MODEL.iProfileThickness }} мм."{% endif %}>{% if CATALOG_MODEL.iProfileThickness > 5 %}{{ CATALOG_MODEL.iProfileThickness }}{% else %}—{% endif %} + + + + 1 %} title="Высота фальца рамы: {{ CATALOG_MODEL.iProfileRabbet }} мм."{% endif %}>{% if CATALOG_MODEL.iProfileRabbet > 1 %}{{ CATALOG_MODEL.iProfileRabbet }}{% else %}—{% endif %} + + + + {{ CATALOG_MODEL.iProfileCameras }} + + + + + + + + + + + + + + + +
Характеристики оконного профиля {{ CATALOG_MODEL.sProfileName }} {% for Star in PROFILE_RATING_STARS %}{% if Star == 0 %}{% else %}{% endif %}{% endfor %} {% if CATALOG_MODEL.fProfileRating > -0.1 %}{{ CATALOG_MODEL.fProfileRating|stringformat:".2f" }}{% endif %}
Производитель:{{ CATALOG_MODEL.sProfileManufacturer }}
Сопротивление теплопередаче Ro (м²×°C/Вт):{% if RANK_PVCP_HEAT_TRANSFER_COLOR != "" %}
{% endif %}
Коэффициент звукоизоляции, (дБ):{% if RANK_PVCP_SOUNDPROOFING_COLOR != "" %}
{% endif %}
Контуров уплотненения (шт.):{% if RANK_PVCP_SEALS_COLOR != "" %}
{% endif %}
Высота в световом проеме, рама+створка (мм):{% if RANK_PVCP_HEIGHT_COLOR != "" %}
{% endif %}
Максимальная толщина стеклопакета (мм):{% if RANK_PVCP_G_THICKNESS_COLOR != "" %}
{% endif %}
Монтажная ширина профиля (мм):{% if RANK_PVCP_THICKNESS_COLOR != "" %}
{% endif %}
Фальц рамы (мм):{% if RANK_PVCP_RABBET_COLOR != "" %}
{% endif %}
Число камер рамы/створки (шт.):{% if RANK_PVCP_CAMERAS_COLOR != "" %}
{% endif %}
Армирование:{{ CATALOG_MODEL.sProfileReinforcement }}
Штапик:
{{ CATALOG_MODEL.sProfileFillet }}
Уплотнитель:{{ CATALOG_MODEL.sProfileSealDescription }}
Цвет:{% if CATALOG_MODEL.sProfileColor == "" %}—{% else %}{{ CATALOG_MODEL.sProfileColor|capfirst }}{% endif %}
{% if LIST_OTHER|length > 1 %} +

Прочие характеристики профиля:

+
    {% for LI_BULL in LIST_OTHER %} +
  • {{ LI_BULL|safe }}
  • {% endfor %} +
{% elif CATALOG_MODEL.sProfileOther != "" %}

Прочие характеристики рамы и створки: {{ CATALOG_MODEL.sProfileOther }}

{% endif %}{% if EXTRA_INFO %} +

Дополнительная информация:

+ {{ EXTRA_INFO|safe }} {% endif %}{% if MERCHANTS|length > 0 %} +

Партнёры «Окнардия» использующие профили {{ CATALOG_MODEL.sProfileName }} в своих предложениях:

+ {% endif %}{% if PROFILES|length > 0 %} +

Другие профили производства {{ CATALOG_MODEL.sProfileManufacturer }}:

+ + + + + {% for i in PROFILES %} + + + + {% endfor %} + +
Марка профилярейтинг
{{ i.PROFILE_NAME }} {% for Star in i.PROFILE_RATING_STARS %}{% if Star == 0 %}{% else %}{% endif %}{% endfor %} {% if i.PROFILE_RATING > -0.1 %}{{ i.PROFILE_RATING|stringformat:".2f" }}{% endif %}
+

Сравнить компонеты рейтинга профилей можно в разделе Ретинги.

{% endif %} +
+
{# --- Описание производителя профилей :: начало --- #}{% if PROFILE_DETAIL|length > 0 %}{% for i in PROFILE_DETAIL %} +{{ i.sPostContent|safe }}{% endfor %}{% else %} +

Извините, описание и иллюстрации марки профилей подготавливаются.
 
Зайдите позже.

{% endif %} + {# --- Описание производителя профилей :: конец --- #}
+ +
+ {# --- Баннер: НАЧАЛО --- #} +

{% include "ad/bannet-wide.html" %}
+ {# --- Баннер: конец --- #} +
+{% include "report/report_last_user_visit.html" %} +{% include "report/report_log_user_visit.html" %} +
+
{% endblock %} diff --git a/oknardia/web/catalog.py b/oknardia/web/catalog.py index ff039c1..98fe02d 100644 --- a/oknardia/web/catalog.py +++ b/oknardia/web/catalog.py @@ -1,10 +1,14 @@ # -*- coding: utf-8 -*- -from django.shortcuts import render +from django.shortcuts import render, redirect from django.http import HttpRequest, HttpResponse from django.utils import timezone +from oknardia.settings import * from oknardia.models import PVCprofiles from web.report1 import get_last_all_user_visit_list, get_last_user_visit_cookies, get_last_user_visit_list +from web.add_func import normalize, get_rating_set_for_stars import time +import json +import random import pytils @@ -27,8 +31,13 @@ def catalog_root(request: HttpRequest) -> HttpResponse: return response -# Каталог профилей (первый уровень) def catalog_profile(request: HttpRequest) -> HttpResponse: + """ + КАТАЛОГ ПРОФИЛЕЙ: страница со списком производителей и моделей (марками) профилей + + :param request: HttpRequest -- входящий http-запрос + :return response: HttpResponse -- исходящий http-ответ + """ template = "catalog/catalog_of_profiles.html" # шаблон time_start = time.time() q_profile = PVCprofiles.objects.raw('SELECT' @@ -104,3 +113,174 @@ def catalog_profile(request: HttpRequest) -> HttpResponse: 'ticks': float(time.time() - time_start) }) return render(request, template, to_template) + + +def catalog_profile_model(request: HttpRequest, manufacture_id: int, manufacture_name: str, + model_id: id, model_name: str) -> HttpResponse: + """ + КАТАЛОГ ПРОФИЛЕЙ: страница с описанием марки профиля + + :param request: HttpRequest -- входящий http-запрос + :param manufacture_id: id профиля. Предполагается, что это первый id при сортировке по sProfileBriefDescription + :param manufacture_name: название производителя (транслитерированное pytils.translit.slugify()) + :param model_id: id модели (марки) профиля + :param model_name: модель (марка) профиля (транслитерированное pytils.translit.slugify(sProfileName)) + :return response: HttpResponse -- исходящий http-ответ + """ + time_start = time.time() + template = "catalog/catalog_of_profiles_model.html" # шаблон + manufacture_id = int(manufacture_id) + model_id = int(model_id) + q_pvc_by_id = PVCprofiles.objects.get(id=model_id) + if pytils.translit.slugify(q_pvc_by_id.sProfileManufacturer) != manufacture_name \ + or pytils.translit.slugify(q_pvc_by_id.sProfileName) != model_name \ + or manufacture_id != model_id: + return redirect(f"/catalog/profile/{model_id}-{pytils.translit.slugify(q_pvc_by_id.sProfileManufacturer)}/" + f"{model_id}-{pytils.translit.slugify(q_pvc_by_id.sProfileName)}") + to_template = {"CATALOG_MODEL": q_pvc_by_id, + "CATALOG_MAN2URL": manufacture_name, + "CATALOG_URL": f"{manufacture_id}-{manufacture_name}", + "CATALOG_URL2": f"{manufacture_id}-{manufacture_name}/{model_id}-{model_name}", + "PROFILE_RATING_STARS": get_rating_set_for_stars(q_pvc_by_id.fProfileRating)} + try: + getted_json = json.loads(q_pvc_by_id.sProfileDescription) + # раскрашиваем кружочки рейтинга напротив характеристик профиля + if KEY_RATING in getted_json: + # RatingReal = True # Рейтинг реальный (профиль представлен в ценовых предложениях) + # кружочки зелёные + rating = getted_json[KEY_RATING] + color = int(255 - rating[RANK_PVCP_CAMERAS_NUM_NAME] * 255) + to_template.update({"RANK_PVCP_CAMERAS_COLOR": f"{color},255,{color}"}) + color = int(255 - rating[RANK_PVCP_SEALS_NAME] * 255) + to_template.update({"RANK_PVCP_SEALS_COLOR": f"{color},255,{color}"}) + color = int(255 - rating[RANK_PVCP_THICKNESS_NAME] * 255) + to_template.update({"RANK_PVCP_THICKNESS_COLOR": f"{color},255,{color}"}) + color = int(255 - rating[RANK_PVCP_G_THICKNESS_NAME] * 255) + to_template.update({"RANK_PVCP_G_THICKNESS_COLOR": f"{color},255,{color}"}) + color = int(255 - rating[RANK_PVCP_RABBET_NAME] * 255) + to_template.update({"RANK_PVCP_RABBET_COLOR": f"{color},255,{color}"}) + color = int(255 - rating[RANK_PVCP_HEAT_TRANSFER_NAME] * 255) + to_template.update({"RANK_PVCP_HEAT_TRANSFER_COLOR": f"{color},255,{color}"}) + color = int(255 - rating[RANK_PVCP_SOUNDPROOFING_NAME] * 255) + to_template.update({"RANK_PVCP_SOUNDPROOFING_COLOR": f"{color},255,{color}"}) + color = int(255 - rating[RANK_PVCP_HEIGHT_NAME] * 255) + to_template.update({"RANK_PVCP_HEIGHT_COLOR": f"{color},255,{color}"}) + elif KEY_RATING_VIRTUAL in getted_json: + # RatingReal = False # Рейтинг виртуальный (профиль представлен в ценовых предложениях) + # кружочки серые + rating = getted_json[KEY_RATING_VIRTUAL] + color = int(255 - rating[RANK_PVCP_CAMERAS_NUM_NAME] * 64) + to_template.update({"RANK_PVCP_CAMERAS_COLOR": f"{color},{color},{color}"}) + color = int(255 - rating[RANK_PVCP_SEALS_NAME] * 64) + to_template.update({"RANK_PVCP_SEALS_COLOR": f"{color},{color},{color}"}) + color = int(255 - rating[RANK_PVCP_THICKNESS_NAME] * 64) + to_template.update({"RANK_PVCP_THICKNESS_COLOR": f"{color},{color},{color}"}) + color = int(255 - rating[RANK_PVCP_G_THICKNESS_NAME] * 64) + to_template.update({"RANK_PVCP_G_THICKNESS_COLOR": f"{color},{color},{color}"}) + color = int(255 - rating[RANK_PVCP_RABBET_NAME] * 64) + to_template.update({"RANK_PVCP_RABBET_COLOR": f"{color},{color},{color}"}) + color = int(255 - rating[RANK_PVCP_HEAT_TRANSFER_NAME] * 64) + to_template.update({"RANK_PVCP_HEAT_TRANSFER_COLOR": f"{color},{color},{color}"}) + color = int(255 - rating[RANK_PVCP_SOUNDPROOFING_NAME] * 64) + to_template.update({"RANK_PVCP_SOUNDPROOFING_COLOR": f"{color},{color},{color}"}) + color = int(255 - rating[RANK_PVCP_HEIGHT_NAME] * 64) + to_template.update({"RANK_PVCP_HEIGHT_COLOR": f"{color},{color},{color}"}) + else: + pass + if KEY_HTML in getted_json: + to_template.update({"EXTRA_INFO": getted_json[KEY_HTML]}) + except (TypeError, ValueError, KeyError): + pass + list_other = [] + for i in q_pvc_by_id.sProfileOther.split(";"): + j = i.find(":") + list_other.append(u"" + i[:j+1] + u"" + i[j+1:]) + to_template.update({"LIST_OTHER": list_other}) + q_merchant = PVCprofiles.objects.raw(f"SELECT" + f" COUNT(oknardia_priceoffer.id) AS offers_by_merchant," + f" oknardia_merchantbrand.sMerchantName," + f" oknardia_merchantbrand.pMerchantLogo," + f" oknardia_merchantbrand.id " + f"FROM oknardia_priceoffer" + f" INNER JOIN oknardia_setkit" + f" ON oknardia_priceoffer.kOffer2SetKit_id = oknardia_setkit.id" + f" INNER JOIN oknardia_pvcprofiles" + f" ON oknardia_setkit.kSet2PVCprofiles_id = oknardia_pvcprofiles.id" + f" INNER JOIN oknardia_ouruser" + f" ON oknardia_setkit.kSet2User_id = oknardia_ouruser.id" + f" INNER JOIN oknardia_merchantoffice" + f" ON oknardia_ouruser.kMerchantOffice_id = oknardia_merchantoffice.id" + f" INNER JOIN oknardia_merchantbrand" + f" ON oknardia_merchantoffice.kMerchantName_id = oknardia_merchantbrand.id " + f"WHERE oknardia_pvcprofiles.id = {model_id} " + f"GROUP BY oknardia_merchantbrand.sMerchantName," + f" oknardia_merchantbrand.pMerchantLogo," + f" oknardia_merchantbrand.id " + f"ORDER BY offers_by_merchant DESC;") + list_merchant = [] + for i in q_merchant: + list_merchant.append({ + "MERCHANT_ID": i.id, + "MERCHANT_NAME": i.sMerchantName, + "MERCHANT_NAME_T": pytils.translit.slugify(i.sMerchantName), + "MERCHANT_LOGO_URL": i.pMerchantLogo, + "MERCHANT_OFFERS": i.offers_by_merchant, + }) + to_template.update({'MERCHANTS': list_merchant}) + q_profiles = PVCprofiles.objects.raw(f"SELECT oknardia_pvcprofiles.id," + f" oknardia_pvcprofiles.fProfileRating," + f" oknardia_pvcprofiles.sProfileBriefDescription," + f" oknardia_pvcprofiles.sProfileName " + f"FROM oknardia_pvcprofiles " + f"WHERE oknardia_pvcprofiles.sProfileManufacturer =" + f" '{q_pvc_by_id.sProfileManufacturer}' " + f"ORDER BY oknardia_pvcprofiles.fProfileRating;") + list_profiles = [] + for i in q_profiles: + if i.id != model_id: + list_profiles.append({ + "PROFILE_NAME": i.sProfileBriefDescription, + "PROFILE_ID": i.id, + "PROFILE_URL": pytils.translit.slugify(i.sProfileName).lower(), + "PROFILE_RATING": i.fProfileRating, + "PROFILE_RATING_STARS": get_rating_set_for_stars(i.fProfileRating), + }) + to_template.update({'PROFILES': list_profiles}) + q_profiles_detail = PVCprofiles.objects.raw(f"SELECT" + f" oknardia_blogposts.*," + f" oknardia_pvcprofiles.id," + f" oknardia_catalog2profile.sCatalogCardType," + f" oknardia_blogposts.iCatalogSort " + f"FROM oknardia_catalog2profile" + f" INNER JOIN oknardia_blogposts" + f" ON oknardia_catalog2profile.kBlogCatalog_id=oknardia_blogposts.id" + f" INNER JOIN oknardia_pvcprofiles" + f" ON oknardia_catalog2profile.kProfile_id=oknardia_pvcprofiles.id " + f"WHERE oknardia_pvcprofiles.id = {model_id} " + f"AND oknardia_catalog2profile.sCatalogCardType =" + f" {CATALOG_RECORD_FOR_PROFILE_MODEL} " + f"ORDER BY oknardia_blogposts.iCatalogSort;") + list_profiles_detail = list(q_profiles_detail) + to_template.update({'PROFILE_DETAIL': list_profiles_detail}) + list_img_for_blog = [] + for i in list_profiles_detail: + if i.sImgForBlogSocial != "": + list_img_for_blog.append(i.sImgForBlogSocial) + if len(list_profiles_detail) > 0: + random.shuffle(list_img_for_blog) + to_template.update({'IMG_FOR_BLOG': list_img_for_blog[0]}) + to_template.update({'PUB_DAT': q_pvc_by_id.dProfileModify}) + if len(list_profiles_detail) > 0: + pub_data = sorted(list_profiles_detail, key=lambda item: item.dPostDataModify)[0].dPostDataModify + print(pub_data, q_pvc_by_id.dProfileModify) + if pub_data.replace(tzinfo=None) < q_pvc_by_id.dProfileModify.replace(tzinfo=None): + to_template.update({'PUB_DAT': pub_data}) + to_template.update({ + # получаем последние визиты клиента через куки + 'LAST_VISIT': get_last_user_visit_list(get_last_user_visit_cookies(request)[:3]), + # получаем последние визиты всех посетителей из базы + # id2log, log_visit = get_last_all_user_visit_list() + 'LOG_VISIT': get_last_all_user_visit_list(), + 'ticks': float(time.time()-time_start) + }) + return render(request, template, to_template)