породы в БД
Gitea Actions Demo / build_and_push (push) Has been cancelled Details

This commit is contained in:
artem 2026-01-13 15:55:27 +03:00
parent ce5c715611
commit e121c6af34
4 changed files with 8130 additions and 0 deletions

84
scripts/assets_fiil.py Normal file
View File

@ -0,0 +1,84 @@
import os
import random
import shutil
from PIL import Image
def copy_convert_to_webp(
source_dir,
dest_dir,
samples_per_folder=5,
size_threshold=1024 * 1024,
quality_high=90,
quality_low=70,
):
"""
Копирует структуру папок и конвертирует изображения в WebP
:param source_dir: Исходная директория с изображениями
:param dest_dir: Целевая директория для копирования
:param samples_per_folder: Количество изображений для выбора из каждой папки
:param size_threshold: Пороговый размер файла (в байтах) для сильного сжатия
:param quality_high: Качество для маленьких изображений (0-100)
:param quality_low: Качество для больших изображений (0-100)
"""
image_extensions = (".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".webp")
def is_image_file(filename):
return filename.lower().endswith(image_extensions)
def convert_to_webp(src_path, dest_path, quality):
try:
with Image.open(src_path) as img:
# Сохраняем прозрачность для RGBA
if img.mode in ("RGBA", "LA"):
img = img.convert("RGBA")
img.save(dest_path, "WEBP", quality=quality, lossless=False, method=6)
else:
# Конвертируем в RGB для JPEG-подобных изображений
img = img.convert("RGB")
img.save(dest_path, "WEBP", quality=quality, method=6)
except Exception as e:
print(f"Error converting {src_path}: {e}")
return False
return True
# Создаем корневую целевую папку
os.makedirs(dest_dir, exist_ok=True)
for root, dirs, files in os.walk(source_dir):
rel_path = os.path.relpath(root, source_dir)
target_dir = os.path.join(dest_dir, rel_path)
os.makedirs(target_dir, exist_ok=True)
images = [f for f in files if is_image_file(f)]
if not images:
continue
selected = random.sample(images, min(samples_per_folder, len(images)))
for file in selected:
src_path = os.path.join(root, file)
base_name = os.path.splitext(file)[0]
dest_path = os.path.join(target_dir, f"{base_name}.webp")
# Определяем качество на основе размера
file_size = os.path.getsize(src_path)
quality = quality_low if file_size > size_threshold else quality_high
# Конвертируем в WebP
if not convert_to_webp(src_path, dest_path, quality):
# Если ошибка конвертации - копируем оригинал
shutil.copy2(src_path, dest_path)
print(f"Copied original file instead: {file}")
if __name__ == "__main__":
copy_convert_to_webp(
source_dir="assets",
dest_dir="webp_output",
samples_per_folder=5,
size_threshold=1 * 1024 * 20, # 1 MB
quality_high=70,
quality_low=70,
)

167
scripts/filldb.py Normal file
View File

@ -0,0 +1,167 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
import_beerds_sql.py
Скрипт читает файлы из каталогов:
- server/modules/descriptions/repository/breed_descriptions
- server/modules/descriptions/repository/breed_signs
и вместо непосредственной вставки генерирует PostgreSQLSQLфайл, который
можно применить через `psql -f <имя_файла.sql>`:
CREATE TABLE beerds.beerds (
id varchar NOT NULL,
name text NOT NULL,
descriptions text NOT NULL,
signs json NOT NULL,
alias text NOT NULL,
CONSTRAINT beerds_pkey PRIMARY KEY (id)
);
"""
import sys
import json
import hashlib
import pathlib
# ------------------------------------------------------------------
# 2⃣ Путь к каталогам (можно изменить под свой проект)
# ------------------------------------------------------------------
BASE_DIR = pathlib.Path(__file__).resolve().parent.parent
DESC_DIR = BASE_DIR / "server/modules/descriptions/repository/breed_descriptions"
SIGN_DIR = BASE_DIR / "server/modules/descriptions/repository/breed_signs"
print(f"DESC_DIR = {DESC_DIR}")
# ------------------------------------------------------------------
# 3⃣ Функции чтения файлов
# ------------------------------------------------------------------
def read_text_file(path: pathlib.Path) -> str:
"""Возвращает содержимое текстового файла (unicode)."""
with path.open("r", encoding="utf-8") as f:
return f.read().strip()
def read_json_file(path: pathlib.Path) -> dict:
"""Возвращает JSONобъект из файла."""
with path.open("r", encoding="utf-8") as f:
return json.load(f)
# ------------------------------------------------------------------
# 4⃣ Формируем словарь: имя → (описание, сигналы)
# ------------------------------------------------------------------
def build_breed_map(desc_dir: pathlib.Path, sign_dir: pathlib.Path) -> dict:
"""Возвращает dict: stem → (description, signs)"""
desc_files = {p.stem: p for p in desc_dir.glob("*.txt")}
sign_files = {p.stem: p for p in sign_dir.glob("*.txt")}
common_keys = desc_files.keys() & sign_files.keys()
if not common_keys:
print("⚠️ Нет общих файлов между каталогами описаний и сигналов.")
return {}
breeds = {}
for key in sorted(common_keys):
desc_path = desc_files[key]
sign_path = sign_files[key]
try:
description = read_text_file(desc_path)
except Exception as e:
print(f"Не удалось прочитать описание {desc_path}: {e}")
continue
try:
signs = read_json_file(sign_path)
except Exception as e:
print(f"Не удалось прочитать сигналы {sign_path}: {e}")
continue
breeds[key] = (description, signs)
return breeds
# ------------------------------------------------------------------
# 5⃣ Генерация id (если нужно уникальное)
# ------------------------------------------------------------------
def generate_id(name: str, alias: str) -> str:
"""Генерирует MD5hash из `name:alias`."""
key = f"{name}:{alias}"
return hashlib.md5(key.encode("utf-8")).hexdigest()
# ------------------------------------------------------------------
# 6⃣ Генерация SQLфайла
# ------------------------------------------------------------------
def write_sql_file(breeds: dict, out_path: pathlib.Path):
"""Создаёт один .sqlфайл, содержащий INSERTоперации для всех пород."""
if not breeds:
print("⚠️ Нет данных для генерации SQL.")
return
lines = []
header = (
"-- Автоматически сгенерированный скрипт вставки пород\n"
"-- Запустить: psql -f beerds_insert.sql\n\n"
"BEGIN;\n"
)
lines.append(header)
# Формируем один блок INSERT с несколькими строками VALUES
# 1. Столбцы
cols = "(id, name, descriptions, signs, alias)"
# 2. Генерируем строки VALUES
value_lines = []
for name, (description, signs) in breeds.items():
alias = name # можно изменить при необходимости
breed_id = generate_id(name, alias)
# Подготовка значений: экранирование апострофов и JSON
escaped_name = name.replace("_", " ").replace("'", "''")
escaped_alias = alias.replace("'", "''")
escaped_desc = description.replace("'", "''")
# JSON как строка (в PostgreSQL json можно передавать как текст)
json_str = json.dumps(signs, ensure_ascii=False).replace("'", "''")
value_line = f"('{breed_id}', '{escaped_name}', '{escaped_desc}', '{json_str}', '{escaped_alias}')"
value_lines.append(value_line)
# Объединяем VALUES через запятую
values_section = ",\n".join(value_lines)
insert_stmt = (
f"INSERT INTO beerds.beerds {cols}\n"
f"VALUES\n{values_section}\n"
f"ON CONFLICT (id) DO UPDATE\n"
f" SET name = EXCLUDED.name,\n"
f" descriptions = EXCLUDED.descriptions,\n"
f" signs = EXCLUDED.signs,\n"
f" alias = EXCLUDED.alias;\n"
)
lines.append(insert_stmt)
lines.append("\nCOMMIT;")
# Записываем в файл
out_path.write_text("\n".join(lines), encoding="utf-8")
print(f"✅ SQLфайл успешно сгенерирован: {out_path}")
# ------------------------------------------------------------------
# 7⃣ Основная точка входа
# ------------------------------------------------------------------
def main():
print("🔍 Читаем файлы…")
breeds_map = build_breed_map(DESC_DIR, SIGN_DIR)
if not breeds_map:
print("❌ Ничего не найдено. Завершение.")
sys.exit(1)
# Путь для вывода SQLфайла
sql_file_path = BASE_DIR / "beerds_insert.sql"
print(f"📝 Записываем INSERTоперации в файл: {sql_file_path}")
write_sql_file(breeds_map, sql_file_path)
print("🎉 Готово!")
if __name__ == "__main__":
main()

View File

@ -0,0 +1,46 @@
import json
from pathlib import Path
def generate_folder_structure(root_path):
result = {}
# Поддерживаемые форматы изображений
image_ext = {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".tiff"}
# Основные категории (cat и dog)
for category in ["cat", "dog"]:
category_path = Path(root_path) / category
if not category_path.is_dir():
continue
category_dict = {}
# Обрабатываем подпапки внутри категории
for subfolder in category_path.iterdir():
if subfolder.is_dir():
# Собираем изображения
images = [
file.name for file in subfolder.iterdir() if file.is_file() and file.suffix.lower() in image_ext
]
category_dict[subfolder.name] = sorted(images)
result[category] = category_dict
return result
def save_to_json(data, output_file):
with open(output_file, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
if __name__ == "__main__":
# Настройки
ASSETS_DIR = "server/static/assets"
OUTPUT_JSON = "structure.json"
# Генерация структуры
structure = generate_folder_structure(ASSETS_DIR)
# Сохранение в файл
save_to_json(structure, OUTPUT_JSON)
print(f"JSON структура сохранена в файл: {OUTPUT_JSON}")

File diff suppressed because it is too large Load Diff