Compare commits
7 Commits
main
...
2026-rewor
| Author | SHA1 | Date | |
|---|---|---|---|
| bcc10de4d4 | |||
| 55f9a74231 | |||
| 49c19d9f92 | |||
| 67a8c093f5 | |||
| e0a5a5739b | |||
| 3e67d6cf71 | |||
| 917bcb42c8 |
32
.gitignore
vendored
32
.gitignore
vendored
@@ -132,4 +132,34 @@ venv.bak/
|
|||||||
dmypy.json
|
dmypy.json
|
||||||
|
|
||||||
# Pyre type checker
|
# Pyre type checker
|
||||||
.pyre/
|
.pyre/
|
||||||
|
|
||||||
|
# MacOS specific files
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Database dumps and backups (CRITICAL - NEVER commit production data!)
|
||||||
|
SQL/
|
||||||
|
*.sql
|
||||||
|
*.dump
|
||||||
|
*.backup
|
||||||
|
*.sql.gz
|
||||||
|
db.json
|
||||||
|
db.json.zip
|
||||||
|
|
||||||
|
# API keys, certificates, and credentials
|
||||||
|
*.key
|
||||||
|
*.pem
|
||||||
|
*.p12
|
||||||
|
*.p8
|
||||||
|
*.crt
|
||||||
|
*.cert
|
||||||
|
|
||||||
|
# IDE and editor specific
|
||||||
|
.vscode/settings.json
|
||||||
|
.idea/vcs.xml
|
||||||
|
.idea/inspectionProfiles/
|
||||||
|
|
||||||
|
# Project specific ignore patterns
|
||||||
|
.github/
|
||||||
|
.log/
|
||||||
|
.logs/
|
||||||
|
|||||||
3
database/.gitignore
vendored
Normal file
3
database/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Это папака для хранения базы данных SQLite, не должна быть в репозитории.
|
||||||
|
*.*
|
||||||
|
*
|
||||||
@@ -1 +0,0 @@
|
|||||||
1
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
ИНСТРУКЦИЯ: скопируйте этот файл в my_secret.py и заполните реальные значения.
|
ИНСТРУКЦИЯ: скопируйте этот файл в my_secret.py и заполните реальные значения.
|
||||||
|
|
||||||
Пример:
|
Пример:
|
||||||
cp oknardia/oknardia/my_secret.py.template oknardia/oknardia/my_secret.py
|
cp oknardia/oknardia/my_secret__sample.py oknardia/oknardia/my_secret.py
|
||||||
# затем отредактируйте значения в my_secret.py
|
# затем отредактируйте значения в my_secret.py
|
||||||
|
|
||||||
ВАЖНО: my_secret.py НИКОГДА не должен быть в git!
|
ВАЖНО: my_secret.py НИКОГДА не должен быть в git!
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ For the full list of settings and their values, see
|
|||||||
https://docs.djangoproject.com/en/4.1/ref/settings/
|
https://docs.djangoproject.com/en/4.1/ref/settings/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from oknardia.my_secret import *
|
from oknardia.my_secret import *
|
||||||
import socket
|
import socket
|
||||||
@@ -18,6 +19,14 @@ import socket
|
|||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
# Переключатель БД для DEV: по умолчанию используем SQLite.
|
||||||
|
# Чтобы вернуть MariaDB на DEV, установите OKNARDIA_USE_SQLITE_DEV=0
|
||||||
|
USE_SQLITE_DEV = os.getenv("OKNARDIA_USE_SQLITE_DEV", "1").strip().lower() in {
|
||||||
|
"1", "true", "yes", "on"
|
||||||
|
}
|
||||||
|
PROJECT_ROOT = BASE_DIR.parent
|
||||||
|
SQLITE_DB_PATH = PROJECT_ROOT / 'database' / 'oknadria.sqlite3'
|
||||||
|
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/
|
||||||
@@ -31,8 +40,8 @@ if socket.gethostname() in MY_HOST_DEV:
|
|||||||
DEBUG = TEMPLATE_DEBUG = True
|
DEBUG = TEMPLATE_DEBUG = True
|
||||||
else:
|
else:
|
||||||
# Все остальные хосты (подразумевается продакшн)
|
# Все остальные хосты (подразумевается продакшн)
|
||||||
DEBUG = TEMPLATE_DEBUG = True
|
# DEBUG = TEMPLATE_DEBUG = True
|
||||||
# DEBUG = TEMPLATE_DEBUG = False
|
DEBUG = TEMPLATE_DEBUG = False
|
||||||
|
|
||||||
ALLOWED_HOSTS = MY_ALLOWED_HOSTS
|
ALLOWED_HOSTS = MY_ALLOWED_HOSTS
|
||||||
|
|
||||||
@@ -123,22 +132,33 @@ if socket.gethostname() in MY_HOST_DEV: # DEBUG: заменяем настр
|
|||||||
MEDIA_ROOT = MY_MEDIA_ROOT_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_MEDIA_ROOT_DEV2
|
MEDIA_ROOT = MY_MEDIA_ROOT_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_MEDIA_ROOT_DEV2
|
||||||
SITEMAP_ROOT = MY_SITEMAP_ROOT_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_SITEMAP_ROOT_DEV2
|
SITEMAP_ROOT = MY_SITEMAP_ROOT_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_SITEMAP_ROOT_DEV2
|
||||||
# STATIC_ROOT = MY_STATIC_ROOT_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_STATIC_ROOT_DEV2
|
# STATIC_ROOT = MY_STATIC_ROOT_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_STATIC_ROOT_DEV2
|
||||||
STATICFILES_DIRS = [
|
dev_static_from_secret = MY_STATIC_ROOT_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_STATIC_ROOT_DEV2
|
||||||
MY_STATIC_ROOT_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_STATIC_ROOT_DEV2,
|
# Если путь из секрета устарел, используем путь текущего репозитория.
|
||||||
]
|
dev_static_fallback = PROJECT_ROOT / 'public' / 'static'
|
||||||
|
dev_static_path = dev_static_from_secret if os.path.isdir(dev_static_from_secret) else str(dev_static_fallback)
|
||||||
|
STATICFILES_DIRS = [dev_static_path]
|
||||||
# путь к каталогу static (в эту переменную использовать для указания пути где будут делаться кэш-блоки для шаблонов)
|
# путь к каталогу static (в эту переменную использовать для указания пути где будут делаться кэш-блоки для шаблонов)
|
||||||
STATIC_BASE_PATH = MY_STATIC_BASE_PATH_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_STATIC_BASE_PATH_DEV2
|
dev_static_base_from_secret = MY_STATIC_BASE_PATH_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_STATIC_BASE_PATH_DEV2
|
||||||
DATABASES = {
|
STATIC_BASE_PATH = dev_static_base_from_secret if os.path.isdir(dev_static_base_from_secret) else str(dev_static_fallback)
|
||||||
'default': {
|
if USE_SQLITE_DEV:
|
||||||
'ENGINE': "django.db.backends.mysql",
|
DATABASES = {
|
||||||
'HOST': MY_DATABASE_HOST_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_DATABASE_HOST_DEV2,
|
'default': {
|
||||||
'PORT': MY_DATABASE_PORT_DEV, # Set to "" for default. Not used with sqlite3.
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': MY_DATABASE_NAME_DEV, # Not used with sqlite3.
|
'NAME': SQLITE_DB_PATH,
|
||||||
'USER': MY_DATABASE_USER_DEV, # Not used with sqlite3.
|
}
|
||||||
'PASSWORD': MY_DATABASE_PASSWORD_DEV, # Not used with sqlite3.
|
}
|
||||||
# 'OPTIONS': { 'autocommit': True, }
|
else:
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': "django.db.backends.mysql",
|
||||||
|
'HOST': MY_DATABASE_HOST_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_DATABASE_HOST_DEV2,
|
||||||
|
'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, }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
TOUCH_RELOAD = MY_TOUCH_RELOAD_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_TOUCH_RELOAD_DEV2
|
TOUCH_RELOAD = MY_TOUCH_RELOAD_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_TOUCH_RELOAD_DEV2
|
||||||
else:
|
else:
|
||||||
MEDIA_ROOT = MY_MEDIA_ROOT_PROD
|
MEDIA_ROOT = MY_MEDIA_ROOT_PROD
|
||||||
@@ -160,6 +180,17 @@ else:
|
|||||||
}
|
}
|
||||||
TOUCH_RELOAD = MY_TOUCH_RELOAD_PROD
|
TOUCH_RELOAD = MY_TOUCH_RELOAD_PROD
|
||||||
|
|
||||||
|
# Для локальной/тестовой разработки можно принудительно включить SQLite даже
|
||||||
|
# если hostname не попал в MY_HOST_DEV. На прод-хостах (MY_HOST_PROD) override
|
||||||
|
# не применяется.
|
||||||
|
if USE_SQLITE_DEV and socket.gethostname() not in MY_HOST_PROD:
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': SQLITE_DB_PATH,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#########################################
|
#########################################
|
||||||
# настройки для почтового сервера (они одинаковые для DEV и PROD)
|
# настройки для почтового сервера (они одинаковые для DEV и PROD)
|
||||||
EMAIL_HOST = MY_EMAIL_HOST_DEV
|
EMAIL_HOST = MY_EMAIL_HOST_DEV
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ urlpatterns = [
|
|||||||
re_path(r'^service/not-denice[/*]$', service.not_denice),
|
re_path(r'^service/not-denice[/*]$', service.not_denice),
|
||||||
# --- создание файлов sitemap.xml
|
# --- создание файлов sitemap.xml
|
||||||
re_path(r'^service/make_sitemaps[/*]$', service.make_site_maps),
|
re_path(r'^service/make_sitemaps[/*]$', service.make_site_maps),
|
||||||
|
re_path(r'^service/make_rating[/*]$', service.make_rating),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,10 @@
|
|||||||
<meta name="generator" content="OKNARDIA 0.3β by Python/Django" />
|
<meta name="generator" content="OKNARDIA 0.3β by Python/Django" />
|
||||||
<title>{% block Title %}{% endblock %} : ОКНАРДИЯ</title>
|
<title>{% block Title %}{% endblock %} : ОКНАРДИЯ</title>
|
||||||
<link rel="alternate" href="https://oknardia.ru" hreflang="ru-ru" />
|
<link rel="alternate" href="https://oknardia.ru" hreflang="ru-ru" />
|
||||||
|
<link rel="icon" href="https://oknardia.ru/favicon.svg" type="image/svg+xml ">
|
||||||
|
<link rel="icon" href="https://oknardia.ru/favicon.png" type="image/png">
|
||||||
|
<link rel="icon" href="https://oknardia.ru/favicon.gif" type="image/gif">
|
||||||
|
<link rel="icon" href="https://oknardia.ru/favicon.ico" type="image/x-icon">
|
||||||
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet" type="text/css" />{# <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />#}
|
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet" type="text/css" />{# <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" />#}
|
||||||
<link href="{% static 'css/bootstrap-theme.min.css' %}" rel="stylesheet" type="text/css" />{# <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css" />#}
|
<link href="{% static 'css/bootstrap-theme.min.css' %}" rel="stylesheet" type="text/css" />{# <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet" type="text/css" />#}
|
||||||
<link href="{% static 'css/oknardia1.css' %}" rel="stylesheet" type="text/css" />{% block Top_CSS1 %}{% endblock %}{% block Top_CSS2 %}{% endblock %}{% block Top_CSS3 %}{% endblock %}
|
<link href="{% static 'css/oknardia1.css' %}" rel="stylesheet" type="text/css" />{% block Top_CSS1 %}{% endblock %}{% block Top_CSS2 %}{% endblock %}{% block Top_CSS3 %}{% endblock %}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
</ul><ul>
|
</ul><ul>
|
||||||
<li><a href="/service/make_FillGeoCode">Добавить GeoCode для адресов где его нет</a></li>
|
<li><a href="/service/make_FillGeoCode">Добавить GeoCode для адресов где его нет</a></li>
|
||||||
</ul><ul>
|
</ul><ul>
|
||||||
<li><a href="/service/make_Rating">Пересчитать рейтинги Профилей</a></li>
|
<li><b><a href="/service/make_rating">Пересчитать рейтинги Профилей</a></b></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ def make_big_img_win_flap(img_file_name_with_path: str, width: int, height: int,
|
|||||||
# height_door = int(height_door)
|
# height_door = int(height_door)
|
||||||
# создаем картинку с нужными размерами
|
# создаем картинку с нужными размерами
|
||||||
img = Image.new("RGBA", (int(width * PICT_H / height_max), PICT_H), (255, 255, 255, 0))
|
img = Image.new("RGBA", (int(width * PICT_H / height_max), PICT_H), (255, 255, 255, 0))
|
||||||
print(img_file_name_with_path)
|
# print(img_file_name_with_path)
|
||||||
# находим крайние точки периметра (если окно -- выравнено вверх; если дверь -- вниз)
|
# находим крайние точки периметра (если окно -- выравнено вверх; если дверь -- вниз)
|
||||||
top = 0
|
top = 0
|
||||||
left = 0
|
left = 0
|
||||||
@@ -592,5 +592,5 @@ def touch_reload_wsgi(s: str = ''):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
with open(TOUCH_RELOAD, 'a', encoding="utf-8") as f:
|
with open(TOUCH_RELOAD, 'a', encoding="utf-8") as f:
|
||||||
f.write(f'\nreload wsgi by cash-template {s}'
|
f.write(f'\nreload wsgi by cash-template - {s} - '
|
||||||
f' {django.utils.dateformat.format(django.utils.timezone.now(), "Y-m-d H:i:s")}')
|
f'{django.utils.dateformat.format(django.utils.timezone.now(), "Y-m-d H:i:s")}')
|
||||||
|
|||||||
@@ -644,7 +644,10 @@ def report_price(request: HttpRequest, build_id: str = "22427", apart_id: str =
|
|||||||
|
|
||||||
# получаем последние визиты всех посетителей из базы
|
# получаем последние визиты всех посетителей из базы
|
||||||
log_visit = get_last_all_user_visit_list()
|
log_visit = get_last_all_user_visit_list()
|
||||||
id_last_visit_log = log_visit[0]['id'] + 1
|
if log_visit[0]['id'] is not None:
|
||||||
|
id_last_visit_log = log_visit[0]['id'] + 1
|
||||||
|
else:
|
||||||
|
id_last_visit_log = 1
|
||||||
# print("id_last_visit_log:", id_last_visit_log)
|
# print("id_last_visit_log:", id_last_visit_log)
|
||||||
to_template.update({'LOG_VISIT': log_visit})
|
to_template.update({'LOG_VISIT': log_visit})
|
||||||
if id_last_visit_log > MAX_LEN_RING_LOG_BUFFER: # максимальный размер циклического буфера
|
if id_last_visit_log > MAX_LEN_RING_LOG_BUFFER: # максимальный размер циклического буфера
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ def service(request: HttpRequest) -> HttpResponse:
|
|||||||
"""
|
"""
|
||||||
time_start = time.time()
|
time_start = time.time()
|
||||||
# проверка на аутентификацию
|
# проверка на аутентификацию
|
||||||
print(request.user.is_authenticated)
|
# print(request.user.is_authenticated)
|
||||||
if not request.user.is_authenticated:
|
if not request.user.is_authenticated:
|
||||||
return redirect("/service/not-denice")
|
return redirect("/service/not-denice")
|
||||||
return render(request, "service/index.html", {'ticks': float(time.time()-time_start)})
|
return render(request, "service/index.html", {'ticks': float(time.time()-time_start)})
|
||||||
@@ -157,7 +157,7 @@ def make_site_maps (request: HttpRequest) -> HttpResponse:
|
|||||||
with open(f"{SITEMAP_ROOT}sitemap.xml", "w", encoding="utf-8") as f:
|
with open(f"{SITEMAP_ROOT}sitemap.xml", "w", encoding="utf-8") as f:
|
||||||
f.write(f"<?xml version='1.0' encoding='UTF-8'?>\n"
|
f.write(f"<?xml version='1.0' encoding='UTF-8'?>\n"
|
||||||
f"<urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'>\n{msg}</urlset>")
|
f"<urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9'>\n{msg}</urlset>")
|
||||||
print(SITEMAP_ROOT)
|
# print(SITEMAP_ROOT)
|
||||||
msg = f"Создан единственный sitemap.xml\nВсего ссылок: {count_total_item:06d}"
|
msg = f"Создан единственный sitemap.xml\nВсего ссылок: {count_total_item:06d}"
|
||||||
else:
|
else:
|
||||||
# Файлов sitemap.xml много.
|
# Файлов sitemap.xml много.
|
||||||
@@ -176,7 +176,7 @@ def make_site_maps (request: HttpRequest) -> HttpResponse:
|
|||||||
f.write(msg)
|
f.write(msg)
|
||||||
msg = f"Создан каскадный sitemap.xml\nВсего вложенных файлов: {count_file+1:04d}\n" \
|
msg = f"Создан каскадный sitemap.xml\nВсего вложенных файлов: {count_file+1:04d}\n" \
|
||||||
f"Всего ссылок: {count_total_item:08d}"
|
f"Всего ссылок: {count_total_item:08d}"
|
||||||
print(msg)
|
# print(msg)
|
||||||
return HttpResponse(f"<pre>{msg}\n\nвремя выполнения: {float(time.time()-time_start)} сек.</pre>")
|
return HttpResponse(f"<pre>{msg}\n\nвремя выполнения: {float(time.time()-time_start)} сек.</pre>")
|
||||||
|
|
||||||
|
|
||||||
@@ -222,3 +222,330 @@ def compare() -> list:
|
|||||||
# print(i1)
|
# print(i1)
|
||||||
# print(f"---------------{count}---------------")
|
# print(f"---------------{count}---------------")
|
||||||
return dim_comp
|
return dim_comp
|
||||||
|
|
||||||
|
|
||||||
|
def make_rating(request: HttpRequest) -> HttpResponse:
|
||||||
|
"""
|
||||||
|
Вычисляем (каждый раз заново) рейтинги оконных профилей, стеклопакетов и оконных наборов.
|
||||||
|
Вычисление базируется на ренкинге. В базовом ренкинге участвуют только стеклопакеты и профиля
|
||||||
|
присутствующие в коммерческих предложениях размещенных в ОКНАРДИИ.
|
||||||
|
|
||||||
|
Ренкинг профилей: Для получения ранка вся совокупность профилей из коммерческих предложений сортируется
|
||||||
|
по тому или иному признаку (характеристике). Каждому профилю присваивается ранк, который вычисляется как
|
||||||
|
весу той или иной характеристики и порядковому номеру профиля в сортированному по этому признаку
|
||||||
|
(характеристике) в списке.
|
||||||
|
|
||||||
|
ВНИМАНИЕ ТЕХНИЧЕСКИЙ ДОЛГ:
|
||||||
|
Система ренкинга разрабатывалась когда в базе было уже достаточно предложений. Возможно, если
|
||||||
|
объектов ренкинга будет мало что-то не сработает. И выдаст ошибку.
|
||||||
|
|
||||||
|
:param request: HttpRequest -- запрос
|
||||||
|
:return: HttpResponse -- ответ
|
||||||
|
"""
|
||||||
|
time_start = time.time()
|
||||||
|
msg = ""
|
||||||
|
# ВЫЧИСЛЯЕМ РЕЙТИНГ ПРОФИЛЕЙ
|
||||||
|
# устанавливаем рейтинг всех профилей в базе в ноль
|
||||||
|
profile_all_num = PVCprofiles.objects.all().update(fProfileRating=0.0)
|
||||||
|
to_template = {'NUM_PROFILE_TOTAL': profile_all_num} # засовываем данные в шаблон
|
||||||
|
q = PVCprofiles.objects.raw("SELECT"
|
||||||
|
" oknardia_pvcprofiles.*,"
|
||||||
|
" COUNT(oknardia_priceoffer.id) AS NumOffer "
|
||||||
|
"FROM oknardia_setkit"
|
||||||
|
" INNER JOIN oknardia_priceoffer"
|
||||||
|
" ON oknardia_setkit.id = oknardia_priceoffer.kOffer2SetKit_id"
|
||||||
|
" RIGHT OUTER JOIN oknardia_pvcprofiles"
|
||||||
|
" ON oknardia_setkit.kSet2PVCprofiles_id = oknardia_pvcprofiles.id "
|
||||||
|
"GROUP BY oknardia_pvcprofiles.id;")
|
||||||
|
profile_use_list = list(q)
|
||||||
|
# получаем словарь из RawQuerySet
|
||||||
|
PVC_Dictionary = Prepare_PVC_Dictionary(profile_use_list)
|
||||||
|
# получаем рейтинги
|
||||||
|
dim, PVC_Dictionary = RankingPVC(PVC_Dictionary)
|
||||||
|
to_template.update(dim) # засовываем данные в шаблон
|
||||||
|
# сортируем по полученному рейтингу
|
||||||
|
PVC_Dictionary = sorted(PVC_Dictionary, key=lambda item: item["TmpRating"])
|
||||||
|
# print u"РЕЙТИНГИ ПРОФИЛЕЙ IN USE"
|
||||||
|
# найдем минимальный и максимальный ранкинг для последующей нормализации
|
||||||
|
NumMaxRank = 0
|
||||||
|
NumMinRank = -1
|
||||||
|
j = 0
|
||||||
|
for i in PVC_Dictionary:
|
||||||
|
if i["NumOffer"] != 0:
|
||||||
|
NumMaxRank = j
|
||||||
|
if NumMinRank == -1:
|
||||||
|
NumMinRank = j
|
||||||
|
j += 1
|
||||||
|
j = 0
|
||||||
|
for i in PVC_Dictionary:
|
||||||
|
obj = PVCprofiles.objects.get(id=i["id"])
|
||||||
|
try:
|
||||||
|
GettedJSON = json.loads(obj.sProfileDescription)
|
||||||
|
except:
|
||||||
|
GettedJSON = {}
|
||||||
|
if i["NumOffer"] != 0:
|
||||||
|
try: del GettedJSON[KEY_RATING_VIRTUAL]
|
||||||
|
except: pass
|
||||||
|
GettedJSON[KEY_RATING] = i["RatingConsist"]
|
||||||
|
# GettedJSON.update({KEY_RATING:i["RatingConsist"]})
|
||||||
|
else:
|
||||||
|
try: del GettedJSON[KEY_RATING]
|
||||||
|
except: pass
|
||||||
|
GettedJSON[KEY_RATING_VIRTUAL] = i["RatingConsist"]
|
||||||
|
# GettedJSON.update({KEY_RATING_VIRTUAL:i["RatingConsist"]})
|
||||||
|
obj.sProfileDescription = json.dumps(GettedJSON,
|
||||||
|
separators=(",",":"),
|
||||||
|
sort_keys=True,
|
||||||
|
encoding="utf-8",
|
||||||
|
ensure_ascii=False)
|
||||||
|
if j <= NumMaxRank:
|
||||||
|
obj.fProfileRating = Normalize(i["TmpRating"],PVC_Dictionary[NumMaxRank]["TmpRating"]) * (RARING_PVC_PROFILE_MAX-RARING_PVC_PROFILE_MIN) + RARING_PVC_PROFILE_MIN
|
||||||
|
else:
|
||||||
|
obj.fProfileRating = 5.0
|
||||||
|
# print "id_PVC:", i["id"], u"\tΣ:", obj.fProfileRating, u"\tСостав:",
|
||||||
|
# print json.dumps(i["RatingConsist"], separators=(",",":"), encoding="utf-8", ensure_ascii=False)
|
||||||
|
obj.save()
|
||||||
|
j += 1
|
||||||
|
# вычисляем рейтинги стеклопакетоа
|
||||||
|
# ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
|
||||||
|
# устанавливаем рейтинг всех стеклопакетоа в базе в ноль
|
||||||
|
GlazingAllNum = Glazing.objects.all().update(fGlazingRating=0.0)
|
||||||
|
to_template.update({'NUM_GLAZING_TOTAL':GlazingAllNum}) # засовываем данные в шаблон
|
||||||
|
q = Glazing.objects.raw("SELECT"
|
||||||
|
" oknardia_glazing.*,"
|
||||||
|
" COUNT(oknardia_priceoffer.id) AS NumOffer "
|
||||||
|
"FROM oknardia_setkit"
|
||||||
|
" INNER JOIN oknardia_priceoffer"
|
||||||
|
" ON oknardia_priceoffer.kOffer2SetKit_id = oknardia_setkit.id"
|
||||||
|
" INNER JOIN oknardia_glazing"
|
||||||
|
" ON oknardia_setkit.kSet2Glazing_id = oknardia_glazing.id "
|
||||||
|
"GROUP BY oknardia_glazing.id;")
|
||||||
|
GlazingUseList = list(q)
|
||||||
|
# получаем словарь из RawQuerySet
|
||||||
|
GLAZ_Dictionary = Prepare_GLAZ_Dictionary(GlazingUseList)
|
||||||
|
# получаем рейтинги
|
||||||
|
dim, GLAZ_Dictionary = RankingGlazing(GLAZ_Dictionary)
|
||||||
|
to_template.update(dim) # засовываем данные в шаблон
|
||||||
|
# сортируем по полученному рейтингу
|
||||||
|
GLAZ_Dictionary = sorted(GLAZ_Dictionary, key=lambda item: item["TmpRating"])
|
||||||
|
# print u"РЕЙТИНГИ СТЕКЛОПАКЕТОВ IN USE"
|
||||||
|
for i in GLAZ_Dictionary:
|
||||||
|
obj = Glazing.objects.get(id=i["id"])
|
||||||
|
obj.fGlazingRating = Normalize(i["TmpRating"], ValMax=GLAZ_Dictionary[-1]["TmpRating"]) * (RARING_GLAZING_MAX-RARING_GLAZING_MIN) + RARING_GLAZING_MIN
|
||||||
|
try:
|
||||||
|
GettedJSON = json.loads(obj.sGlazingDescription)
|
||||||
|
except:
|
||||||
|
GettedJSON = {}
|
||||||
|
try: del GettedJSON[KEY_RATING_VIRTUAL]
|
||||||
|
except: pass
|
||||||
|
GettedJSON.update({KEY_RATING:i["RatingConsist"]})
|
||||||
|
obj.sGlazingDescription = json.dumps(GettedJSON,
|
||||||
|
separators=(",",":"),
|
||||||
|
sort_keys=True,
|
||||||
|
encoding="utf-8",
|
||||||
|
ensure_ascii=False)
|
||||||
|
# print u"id:",i["id"], u"\tRank:", i["TmpRating"], u"\rate:", obj.fGlazingRating, u"\tGLAZ:", i["sGlazingMark"]
|
||||||
|
obj.save()
|
||||||
|
# получаем все стеклопакеты, чтобы забацать рейтинг и для тех, которые есть в каталоге но нет в КП
|
||||||
|
q = Glazing.objects.raw("SELECT oknardia_glazing.* "
|
||||||
|
"FROM oknardia_glazing;")
|
||||||
|
GlazingAllList = list(q)
|
||||||
|
# получаем словарь из RawQuerySet
|
||||||
|
GLAZ_Dictionary = Prepare_GLAZ_Dictionary(GlazingAllList)
|
||||||
|
# получаем рейтинги
|
||||||
|
dim, GLAZ_Dictionary = RankingGlazing(GLAZ_Dictionary)
|
||||||
|
GLAZ_Dictionary = sorted(GLAZ_Dictionary, key=lambda item: item["TmpRating"])
|
||||||
|
if GlazingAllNum > len(GlazingUseList):
|
||||||
|
CutStartIndex = -1
|
||||||
|
CutStartRatingValue = 0.
|
||||||
|
CutEndIndex = -1
|
||||||
|
CutEndRatingValue = 0.
|
||||||
|
for i in range(0, GlazingAllNum):
|
||||||
|
# print i, GLAZ_Dictionary[i]["id"], u"\trank --> ", GLAZ_Dictionary[i]["TmpRating"], "\t(",
|
||||||
|
# print GLAZ_Dictionary[i]["fGlazingRating"], ")\tFormulaGLAZING:", GLAZ_Dictionary[i]["sGlazingMark"]
|
||||||
|
if GLAZ_Dictionary[i]["fGlazingRating"] != 0.:
|
||||||
|
# нашли конец следующего отрезка, нужно отрезок переопределить
|
||||||
|
CutStartRatingValue = CutEndRatingValue
|
||||||
|
CutStartIndex = CutEndIndex
|
||||||
|
CutEndRatingValue = GLAZ_Dictionary[i]["fGlazingRating"]
|
||||||
|
CutEndIndex = i
|
||||||
|
if CutEndIndex == 0:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
# надо перебрать все объекты внутри отрезка
|
||||||
|
for j in range(CutStartIndex+1, CutEndIndex):
|
||||||
|
# и пересчитать рейтинги внутри этого, нового отрезка
|
||||||
|
GLAZ_Dictionary[j]["fGlazingRating"] = CutStartRatingValue + (GLAZ_Dictionary[j]["TmpRating"]-GLAZ_Dictionary[CutStartIndex]["TmpRating"])*((CutEndRatingValue-CutStartRatingValue)/(GLAZ_Dictionary[CutEndIndex]["TmpRating"]-GLAZ_Dictionary[CutStartIndex]["TmpRating"]))
|
||||||
|
# print j, GLAZ_Dictionary[j]["id"], u"\trank >>> ", GLAZ_Dictionary[j]["TmpRating"], "\t(",
|
||||||
|
# print GLAZ_Dictionary[j]["fGlazingRating"], ")\tFormulaGLAZING:", GLAZ_Dictionary[j]["sGlazingMark"]
|
||||||
|
# и записать этот рейтинг в базу
|
||||||
|
obj = Glazing.objects.get(id=GLAZ_Dictionary[j]["id"])
|
||||||
|
obj.fGlazingRating = GLAZ_Dictionary[j]["fGlazingRating"]
|
||||||
|
try:
|
||||||
|
GettedJSON = json.loads(obj.sGlazingDescription)
|
||||||
|
except:
|
||||||
|
GettedJSON = {}
|
||||||
|
try: del GettedJSON[KEY_RATING]
|
||||||
|
except: pass
|
||||||
|
GettedJSON.update({KEY_RATING_VIRTUAL:GLAZ_Dictionary[j]["RatingConsist"]})
|
||||||
|
obj.sGlazingDescription = json.dumps(GettedJSON,
|
||||||
|
separators=(",",":"),
|
||||||
|
sort_keys=True,
|
||||||
|
encoding="utf-8",
|
||||||
|
ensure_ascii=False)
|
||||||
|
obj.save()
|
||||||
|
for j in range(CutEndIndex+1, GlazingAllNum):
|
||||||
|
# пересчитать рейтинги хвоста (для отрезка после последнего отрейтингованного)
|
||||||
|
# внимание это код не для работы со словарями. при ревизии переделать GlazingAllList[j].fGlazingRating = CutStartRatingValue + (GlazingAllList[j].TmpRating-GlazingAllList[CutStartIndex].TmpRating)*((CutEndRatingValue-CutStartRatingValue)/(GlazingAllList[CutEndIndex].TmpRating-GlazingAllList[CutStartIndex].TmpRating))
|
||||||
|
GLAZ_Dictionary[j]["fGlazingRating"] = RARING_GLAZING_MAX # т.к. для виртуальный рейтинг иногда снижается, то ставим 5*
|
||||||
|
# и записать этот рейтинг в базу
|
||||||
|
obj = Glazing.objects.get(id=GLAZ_Dictionary[j]["id"])
|
||||||
|
obj.fGlazingRating = GLAZ_Dictionary[j]["fGlazingRating"]
|
||||||
|
try:
|
||||||
|
GettedJSON = json.loads(obj.sGlazingDescription)
|
||||||
|
except:
|
||||||
|
GettedJSON = {}
|
||||||
|
try: del GettedJSON[KEY_RATING]
|
||||||
|
except: pass
|
||||||
|
GettedJSON.update({KEY_RATING_VIRTUAL:GLAZ_Dictionary[j]["RatingConsist"]})
|
||||||
|
obj.sGlazingDescription = json.dumps(GettedJSON,
|
||||||
|
separators=(",",":"),
|
||||||
|
sort_keys=True,
|
||||||
|
encoding="utf-8",
|
||||||
|
ensure_ascii=False)
|
||||||
|
|
||||||
|
obj.save()
|
||||||
|
# вычисляем рейтинги наборов (стеклопакет + профиль + сопутсвующие услуги т.п.
|
||||||
|
# ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░
|
||||||
|
# устанавливаем рейтинг всех наборов в базе в ноль
|
||||||
|
SetAllNum = SetKit.objects.all().update(fSetRating=0.0)
|
||||||
|
to_template.update({'NUM_SET_TOTAL':SetAllNum}) # засовываем данные в шаблон
|
||||||
|
q = SetKit.objects.raw("SELECT"
|
||||||
|
" COUNT(oknardia_priceoffer.id) AS NumOffer,"
|
||||||
|
" MAX(oknardia_priceoffer.dOfferModify) AS dModify,"
|
||||||
|
" oknardia_pvcprofiles.fProfileRating,"
|
||||||
|
" oknardia_glazing.fGlazingRating,"
|
||||||
|
" oknardia_setkit.*,"
|
||||||
|
" oknardia_merchantoffice.sOfficeDiscountMetaFormula "
|
||||||
|
"FROM oknardia_setkit"
|
||||||
|
" INNER JOIN oknardia_priceoffer"
|
||||||
|
" ON oknardia_priceoffer.kOffer2SetKit_id = oknardia_setkit.id"
|
||||||
|
" INNER JOIN oknardia_glazing"
|
||||||
|
" ON oknardia_setkit.kSet2Glazing_id = oknardia_glazing.id"
|
||||||
|
" INNER JOIN oknardia_pvcprofiles"
|
||||||
|
" ON oknardia_pvcprofiles.id = oknardia_setkit.kSet2PVCprofiles_id "
|
||||||
|
" INNER JOIN oknardia_ouruser"
|
||||||
|
" ON oknardia_setkit.kSet2User_id = oknardia_ouruser.id"
|
||||||
|
" INNER JOIN oknardia_merchantoffice"
|
||||||
|
" ON oknardia_ouruser.kMerchantOffice_id = oknardia_merchantoffice.id "
|
||||||
|
"WHERE oknardia_setkit.sSetActive = TRUE "
|
||||||
|
"GROUP BY oknardia_pvcprofiles.fProfileRating,"
|
||||||
|
" oknardia_glazing.fGlazingRating,"
|
||||||
|
" oknardia_merchantoffice.sOfficeDiscountMetaFormula,"
|
||||||
|
" oknardia_setkit.sSetActive, oknardia_setkit.id "
|
||||||
|
"ORDER BY MAX(oknardia_priceoffer.dOfferModify);")
|
||||||
|
# q = SetKit.objects.order_by("dModify")
|
||||||
|
SetUseList = list(q)
|
||||||
|
to_template.update({'NUM_SET': len(SetUseList) })
|
||||||
|
SetDictionary = []
|
||||||
|
# Превратим RawQuerySet в массив словарей (почти JSON). Так получится избежать "макаронного кода".
|
||||||
|
# Заодно переопределяем для правильного ранжирования некоторые параметры из строк в цифры.
|
||||||
|
for i in range(0,len(SetUseList)):
|
||||||
|
SetDictionary.append(q[i].__dict__)
|
||||||
|
if SetDictionary[i]["sSetSill"].lower() in [u"нет",u"-",u"—",""," "]:
|
||||||
|
SetDictionary[i]["sSetSill"] = 0 # Подоконника нет
|
||||||
|
else: SetDictionary[i]["sSetSill"] = 1 # Подоконник есть
|
||||||
|
if SetDictionary[i]["sSetPanes"].lower() in [u"нет",u"-",u"—",""," "]:
|
||||||
|
SetDictionary[i]["sSetPanes"] = 0 # Водоотлив нет
|
||||||
|
else: SetDictionary[i]["sSetPanes"] = 1 # Водоотлив есть
|
||||||
|
if SetDictionary[i]["sSetSlope"].lower() in [u"нет",u"-",u"—",""," "]:
|
||||||
|
SetDictionary[i]["sSetSlope"] = 0 # Откос нет
|
||||||
|
else: SetDictionary[i]["sSetSlope"] = 1 # Откос есть
|
||||||
|
if SetDictionary[i]["sSetClimateControl"].lower() in [u"нет",u"-",u"—",""," "]:
|
||||||
|
SetDictionary[i]["sSetClimateControl"] = 0 # Климат-контроль нет
|
||||||
|
else: SetDictionary[i]["sSetClimateControl"] = 1 # Климат-контроль есть
|
||||||
|
try:
|
||||||
|
# print eval(SetDictionary[i]["sOfficeDiscountMetaFormula"])[KEY_DICSOUNT].keys()
|
||||||
|
# print max(eval(SetDictionary[i]["sOfficeDiscountMetaFormula"])[KEY_DICSOUNT].values())
|
||||||
|
SetDictionary[i].update({"DiscountMax": max(eval(SetDictionary[i]["sOfficeDiscountMetaFormula"])[KEY_DICSOUNT].values())})
|
||||||
|
SetDictionary[i]["sOfficeDiscountMetaFormula"] = len(eval(SetDictionary[i]["sOfficeDiscountMetaFormula"])[KEY_DICSOUNT].keys())
|
||||||
|
except:
|
||||||
|
SetDictionary[i].update({"DiscountMax": 0})
|
||||||
|
SetDictionary[i]["sOfficeDiscountMetaFormula"] = 0
|
||||||
|
# Отранжируем наборы по параметру "дата последнего обновления цены" -- ПО ВОЗРАСТАНИЮ
|
||||||
|
SetDictionary, MaxRank = GetRank(SetDictionary, "dModify", key_weight=RANK_STEP_SET_MODIFY,
|
||||||
|
rank_name=u"Актуальность", revers=False)
|
||||||
|
to_template.update({'S_Modify_Step': RANK_STEP_SET_MODIFY })
|
||||||
|
to_template.update({'S_Modify_MaxRank': MaxRank })
|
||||||
|
# Отранжируем наборы по параметру "доставка включена в стоимость" -- ПО ВОЗРАСТАНИЮ
|
||||||
|
SetDictionary, MaxRank = GetRank(SetDictionary, "bSetDelivery", key_weight=RANK_STEP_SET_DELIVERY,
|
||||||
|
rank_name=u"Доставка", revers=False)
|
||||||
|
to_template.update({'S_Delivery_Step': RANK_STEP_SET_DELIVERY })
|
||||||
|
to_template.update({'S_Delivery_MaxRank': MaxRank })
|
||||||
|
# Отранжируем наборы по параметру Демонтаж/Монтаж" -- ПО ВОЗРАСТАНИЮ
|
||||||
|
SetDictionary, MaxRank = GetRank(SetDictionary, "bSetUninstallInstall", key_weight=RANK_STEP_SET_UNINSTALL_INSTALL,
|
||||||
|
rank_name=u"Монтаж")
|
||||||
|
to_template.update({'S_UninstallInstall_Step': RANK_STEP_SET_UNINSTALL_INSTALL })
|
||||||
|
to_template.update({'S_UninstallInstall_MaxRank': MaxRank })
|
||||||
|
# Отранжируем наборы по параметру Подоконник" -- ПО ВОЗРАСТАНИЮ
|
||||||
|
SetDictionary, MaxRank = GetRank(SetDictionary, "sSetSill", key_weight=RANK_STEP_SET_SILL,
|
||||||
|
rank_name=u"Подоконник")
|
||||||
|
to_template.update({'S_Sill_Step': RANK_STEP_SET_SILL })
|
||||||
|
to_template.update({'S_Sill_MaxRank': MaxRank })
|
||||||
|
# Отранжируем наборы по параметру Водоотлив" -- ПО ВОЗРАСТАНИЮ
|
||||||
|
SetDictionary, MaxRank = GetRank(SetDictionary, "sSetPanes", key_weight=RANK_STEP_SET_PANES,
|
||||||
|
rank_name=u"Водоотлив")
|
||||||
|
to_template.update({'S_Panes_Step': RANK_STEP_SET_PANES })
|
||||||
|
to_template.update({'S_Panes_MaxRank': MaxRank })
|
||||||
|
# Отранжируем наборы по параметру Откос" -- ПО ВОЗРАСТАНИЮ
|
||||||
|
SetDictionary, MaxRank = GetRank(SetDictionary, "sSetSlope", key_weight=RANK_STEP_SET_SLOPE,
|
||||||
|
rank_name=u"Откос")
|
||||||
|
to_template.update({'S_Slope_Step': RANK_STEP_SET_SLOPE })
|
||||||
|
to_template.update({'S_Slope_MaxRank': MaxRank })
|
||||||
|
# Отранжируем наборы по параметру Климат-контроль" -- ПО ВОЗРАСТАНИЮ
|
||||||
|
SetDictionary, MaxRank = GetRank(SetDictionary, "sSetClimateControl", key_weight=RANK_STEP_SET_CLIMATE_CONTROL,
|
||||||
|
rank_name=u"Климат-контроль")
|
||||||
|
to_template.update({'S_ClimateControl_Step': RANK_STEP_SET_CLIMATE_CONTROL })
|
||||||
|
to_template.update({'S_ClimateControl_MaxRank': MaxRank })
|
||||||
|
# Отранжируем наборы по параметру Число предложений -- ПО ВОЗРАСТАНИЮ
|
||||||
|
SetDictionary, MaxRank = GetRank(SetDictionary, "NumOffer", key_weight=RANK_STEP_SET_NUM_OFFER,
|
||||||
|
rank_name=u"Число предложений")
|
||||||
|
to_template.update({'S_NumOffer_Step': RANK_STEP_SET_NUM_OFFER })
|
||||||
|
to_template.update({'S_NumOffer_MaxRank': MaxRank })
|
||||||
|
# Отранжируем наборы по параметру Гибкие скидки -- ПО ВОЗРАСТАНИЮ
|
||||||
|
SetDictionary, MaxRank = GetRank(SetDictionary, "sOfficeDiscountMetaFormula", key_weight=RANK_STEP_DISCOUNT_FLEX,
|
||||||
|
rank_name=u"Гибкость скидок")
|
||||||
|
to_template.update({'S_DiscountFlex_Step': RANK_STEP_DISCOUNT_FLEX })
|
||||||
|
to_template.update({'S_DiscountFlex_MaxRank': MaxRank })
|
||||||
|
# Отранжируем наборы по параметру Гибкие скидки -- ПО ВОЗРАСТАНИЮ
|
||||||
|
SetDictionary, MaxRank = GetRank(SetDictionary, "DiscountMax", key_weight=RANK_STEP_DISCOUNT_MAX,
|
||||||
|
rank_name=u"Размеры скидок")
|
||||||
|
to_template.update({'S_DiscountMax_Step': RANK_STEP_DISCOUNT_MAX })
|
||||||
|
to_template.update({'S_DiscountMax_MaxRank': MaxRank })
|
||||||
|
# расчитываем обзий рейтинг наборов и записываем в базу
|
||||||
|
SetDictionary = sorted(SetDictionary, key=lambda item: item["TmpRating"])
|
||||||
|
# print u"РЕЙТИНГИ НАБОРОВ"
|
||||||
|
for i in SetDictionary:
|
||||||
|
obj = SetKit.objects.get(id=i["id"])
|
||||||
|
try:
|
||||||
|
GettedJSON = json.loads(obj.sSetDescription)
|
||||||
|
except:
|
||||||
|
GettedJSON = {}
|
||||||
|
# нормализованный рейтинг сета
|
||||||
|
# print GettedJSON
|
||||||
|
k1 = Normalize(i["TmpRating"], SetDictionary[-1]["TmpRating"] )*(RARING_SET_MAX-RARING_WEIGHT_PVC_PROFILE_IN_SET-RARING_WEIGHT_GLAZING_IN_SET-RARING_SET_MIN)
|
||||||
|
k2 = Normalize(i["fGlazingRating"], RARING_GLAZING_MAX) * RARING_WEIGHT_GLAZING_IN_SET
|
||||||
|
k3 = Normalize(i["fProfileRating"], RARING_PVC_PROFILE_MAX) * RARING_WEIGHT_PVC_PROFILE_IN_SET
|
||||||
|
# print "id:", i["id"], u"\tk1:", k1, u"\tk2", k2, u"\tk3", k3, u"\tΣ:", k1+k2+k3
|
||||||
|
obj.fSetRating = k1+k2+k3
|
||||||
|
# print str(i["RatingConsist"])
|
||||||
|
try: del GettedJSON[KEY_RATING_VIRTUAL]
|
||||||
|
except: pass
|
||||||
|
GettedJSON.update({KEY_RATING:i["RatingConsist"]})
|
||||||
|
obj.sSetDescription = json.dumps(GettedJSON, separators=(",",":"), encoding="utf-8", ensure_ascii=False)
|
||||||
|
# print obj.sSetDescription
|
||||||
|
obj.save()
|
||||||
|
# print u"id:",i["id"], u"\tRank:", i["TmpRating"], u"\tRate:", obj.fSetRating, u"\tSet:", i["sSetName"], i["fProfileRating"], i["fGlazingRating"]
|
||||||
|
to_template.update({'msg': msg})
|
||||||
|
to_template.update({'ticks': float(time.time()-time_start)})
|
||||||
|
return render(request, "service/make_rating.html", to_template)
|
||||||
Reference in New Issue
Block a user