minor: переименован ключ для синонимов в метаданных ("SYNONYM" -> "KEY_SYNONYM_EN") и переменная для него (KEY_SYNONYM -> KEY_SYNONYM_EN)
This commit is contained in:
+13
-13
@@ -16,7 +16,7 @@ from django.utils.html import mark_safe
|
||||
from django.http import HttpRequest
|
||||
from django.db.models import Model
|
||||
from lpon_site.settings import (
|
||||
SLUG_MAX_LENGTH, KEY_SYNONYM,
|
||||
SLUG_MAX_LENGTH, KEY_SYNONYM_EN,
|
||||
)
|
||||
|
||||
|
||||
@@ -223,10 +223,10 @@ def update_synonyms_in_metadata(
|
||||
Универсальный хелпер для управления синонимами во всех моделях (TbLabel, TbArtist, TbMusicStyle и т.д.)
|
||||
|
||||
Логика:
|
||||
- При создании новой записи: добавляет текущее значение поля в SYNONYM
|
||||
- При редактировании: если значение поля изменилось, добавляет ОБА (старое и новое) в SYNONYM
|
||||
- При создании новой записи: добавляет текущее значение поля в SYN_EN
|
||||
- При редактировании: если значение поля изменилось, добавляет ОБА (старое и новое) в SYN_EN
|
||||
- Очищает дубликаты в списке синонимов, сохраняя порядок
|
||||
- Использует KEY_SYNONYM из settings как ключ в metadata словаре
|
||||
- Использует KEY_SYN_EN из settings как ключ в metadata словаре
|
||||
|
||||
Args:
|
||||
instance: Экземпляр модели (self из save методе). Обязателен!
|
||||
@@ -282,25 +282,25 @@ def update_synonyms_in_metadata(
|
||||
setattr(instance, metadata_field_name, metadata_dict)
|
||||
|
||||
# Убеждаемся, что ключ 'SYNONYM' существует и это список
|
||||
if KEY_SYNONYM not in metadata_dict or not isinstance(metadata_dict[KEY_SYNONYM], list):
|
||||
metadata_dict[KEY_SYNONYM] = []
|
||||
if KEY_SYNONYM_EN not in metadata_dict or not isinstance(metadata_dict[KEY_SYNONYM_EN], list):
|
||||
metadata_dict[KEY_SYNONYM_EN] = []
|
||||
|
||||
# ===== ДОБАВЛЯЕМ СИНОНИМЫ =====
|
||||
# Добавляем синонимы при создании ИЛИ если значение поля изменилось
|
||||
if is_new or old_field_value != current_field_value:
|
||||
# Если поле было обновлено и значение изменилось - добавляем старое значение
|
||||
if old_field_value and old_field_value not in metadata_dict[KEY_SYNONYM]:
|
||||
metadata_dict[KEY_SYNONYM].append(old_field_value)
|
||||
if old_field_value and old_field_value not in metadata_dict[KEY_SYNONYM_EN]:
|
||||
metadata_dict[KEY_SYNONYM_EN].append(old_field_value)
|
||||
|
||||
# Добавляем текущее значение если его еще нет в синонимах
|
||||
if current_field_value not in metadata_dict[KEY_SYNONYM]:
|
||||
metadata_dict[KEY_SYNONYM].append(current_field_value)
|
||||
if current_field_value not in metadata_dict[KEY_SYNONYM_EN]:
|
||||
metadata_dict[KEY_SYNONYM_EN].append(current_field_value)
|
||||
|
||||
# ===== ОЧИЩАЕМ ДУБЛИКАТЫ =====
|
||||
# Удаляем дубликаты в списке синонимов, сохраняя порядок
|
||||
# (может случиться если пользователь вручную редактировал метаданные)
|
||||
if KEY_SYNONYM in metadata_dict and isinstance(metadata_dict[KEY_SYNONYM], list):
|
||||
metadata_dict[KEY_SYNONYM] = list(dict.fromkeys(metadata_dict[KEY_SYNONYM]))
|
||||
if KEY_SYNONYM_EN in metadata_dict and isinstance(metadata_dict[KEY_SYNONYM_EN], list):
|
||||
metadata_dict[KEY_SYNONYM_EN] = list(dict.fromkeys(metadata_dict[KEY_SYNONYM_EN]))
|
||||
|
||||
# ===== СООБЩАЕМ DJANGO ЧТО ПОЛЕ ИЗМЕНИЛОСЬ =====
|
||||
# Для JSONField нужно явно сообщить что мы изменили содержимое
|
||||
@@ -383,7 +383,7 @@ def create_or_get_related_article(
|
||||
|
||||
# Собираем синонимы из метаданных для SEO ключевых слов и исключаем текущее значение поля
|
||||
# из списка (оно будет добавлено первым для приоритета)
|
||||
other_synonyms = [s for s in instance.__dict__.get(metadata_field_name, {}).get(KEY_SYNONYM, []) if str(s) != main_field_value]
|
||||
other_synonyms = [s for s in instance.__dict__.get(metadata_field_name, {}).get(KEY_SYNONYM_EN, []) if str(s) != main_field_value]
|
||||
|
||||
# Собираем все синонимы с текущим значением первым
|
||||
all_synonyms = [main_field_value] + other_synonyms if other_synonyms else [main_field_value]
|
||||
|
||||
@@ -14,7 +14,7 @@ from django.http import HttpRequest
|
||||
from django.forms import ModelForm
|
||||
from django.contrib import messages
|
||||
from lpon_site.settings import (
|
||||
KEY_SYNONYM,
|
||||
KEY_SYNONYM_EN,
|
||||
VALIDATE_KEY__MATCH_TYPE, VALIDATE_KEY__MODEL, VALIDATE_KEY__VALUE,
|
||||
ValidateMatchType, MIN_SYNONYM_WORD_LENGTH
|
||||
)
|
||||
@@ -143,7 +143,7 @@ def validate_for_duplicates(
|
||||
})
|
||||
return duplicates_found
|
||||
|
||||
# ПРОВЕРКА 2: SYNONYM MATCH (совпадение с синонимами в метаданных других записей)
|
||||
# ПРОВЕРКА 2:SYN_ENMATCH (совпадение с синонимами в метаданных других записей)
|
||||
# Ищем: есть ли текущее значение main_field в синонимах других записей?
|
||||
# Например, если у записи A синонимы=['Sony Music', 'SME Records'],
|
||||
# а мы добавляем запись B с основным полем 'Sony Music', это совпадение!
|
||||
@@ -159,7 +159,7 @@ def validate_for_duplicates(
|
||||
has_synonym=RawSQL(
|
||||
f"""
|
||||
EXISTS (
|
||||
SELECT 1 FROM json_each({metadata_field_name}, '$.{KEY_SYNONYM}')
|
||||
SELECT 1 FROM json_each({metadata_field_name}, '$.{KEY_SYNONYM_EN}')
|
||||
WHERE LOWER(json_each.value) = %s
|
||||
)
|
||||
""",
|
||||
@@ -179,8 +179,8 @@ def validate_for_duplicates(
|
||||
# основное поле + все синонимы из метаданных
|
||||
# Этот список переиспользуется на этапах 3 и 4, избегая дублирования логики
|
||||
raw_values_to_analyze = [main_field_value]
|
||||
if KEY_SYNONYM in metadata_dict and isinstance(metadata_dict[KEY_SYNONYM], list):
|
||||
raw_values_to_analyze.extend(metadata_dict[KEY_SYNONYM])
|
||||
if KEY_SYNONYM_EN in metadata_dict and isinstance(metadata_dict[KEY_SYNONYM_EN], list):
|
||||
raw_values_to_analyze.extend(metadata_dict[KEY_SYNONYM_EN])
|
||||
|
||||
# ПРОВЕРКА 3: EXACT_SYNONYM_MATCH (точное совпадение синонимов текущей записи с синонимами других)
|
||||
# Ищем: есть ли синонимы из текущей записи в синонимах других записей?
|
||||
@@ -188,10 +188,10 @@ def validate_for_duplicates(
|
||||
# Например, если текущая запись имеет синонимы=['Polydor Records', 'Vertigo France'],
|
||||
# а запись A имеет синонимы=['Vertigo France', 'Swirl'], это совпадение!
|
||||
# Пользователь подтверждает - удалим конфликтующие синонимы из других записей.
|
||||
if KEY_SYNONYM in metadata_dict and isinstance(metadata_dict[KEY_SYNONYM], list):
|
||||
if KEY_SYNONYM_EN in metadata_dict and isinstance(metadata_dict[KEY_SYNONYM_EN], list):
|
||||
# Собираем все синонимы текущей записи с нормализацией
|
||||
current_synonyms = [
|
||||
normalize_string(syn) for syn in metadata_dict[KEY_SYNONYM]
|
||||
normalize_string(syn) for syn in metadata_dict[KEY_SYNONYM_EN]
|
||||
]
|
||||
|
||||
# Удаляем дубликаты синонимов, сохраняя порядок
|
||||
@@ -215,7 +215,7 @@ def validate_for_duplicates(
|
||||
query_params = []
|
||||
for normalized_synonym in current_synonyms:
|
||||
synonym_query_parts.append(
|
||||
f"EXISTS (SELECT 1 FROM json_each({metadata_field_name}, '$.{KEY_SYNONYM}') WHERE LOWER(json_each.value) = %s)"
|
||||
f"EXISTS (SELECT 1 FROM json_each({metadata_field_name}, '$.{KEY_SYNONYM_EN}') WHERE LOWER(json_each.value) = %s)"
|
||||
)
|
||||
query_params.append(normalized_synonym)
|
||||
|
||||
@@ -283,7 +283,7 @@ def validate_for_duplicates(
|
||||
if len(word) >= effective_min_word_len:
|
||||
word_search_conditions.append(
|
||||
f"""EXISTS (
|
||||
SELECT 1 FROM json_each({metadata_field_name}, '$.{KEY_SYNONYM}')
|
||||
SELECT 1 FROM json_each({metadata_field_name}, '$.{KEY_SYNONYM_EN}')
|
||||
WHERE LOWER(json_each.value) LIKE %s
|
||||
)"""
|
||||
)
|
||||
@@ -343,7 +343,7 @@ def remove_conflicting_synonyms_from_duplicates(
|
||||
remove_conflicting_synonyms_from_duplicates(
|
||||
duplicates_queryset,
|
||||
'j_label_metadata',
|
||||
metadata_dict.get(KEY_SYNONYM) or [],
|
||||
metadata_dict.get(KEY_SYNONYM_EN) or [],
|
||||
)
|
||||
"""
|
||||
# Нормализуем синонимы для удаления один раз
|
||||
@@ -354,10 +354,10 @@ def remove_conflicting_synonyms_from_duplicates(
|
||||
dup_metadata = getattr(duplicate_record, metadata_field_name) or {}
|
||||
|
||||
# Если в метаданных есть синонимы, удаляем те, которые совпадают с нашим списком
|
||||
if KEY_SYNONYM in dup_metadata and isinstance(dup_metadata[KEY_SYNONYM], list):
|
||||
if KEY_SYNONYM_EN in dup_metadata and isinstance(dup_metadata[KEY_SYNONYM_EN], list):
|
||||
# Удаляем синонимы, которые совпадают с переданным списком
|
||||
dup_metadata[KEY_SYNONYM] = [
|
||||
syn for syn in dup_metadata[KEY_SYNONYM]
|
||||
dup_metadata[KEY_SYNONYM_EN] = [
|
||||
syn for syn in dup_metadata[KEY_SYNONYM_EN]
|
||||
if normalize_string(syn) not in normalized_to_remove
|
||||
]
|
||||
# Сохраняем обновленные метаданные
|
||||
@@ -403,7 +403,7 @@ def build_search_report(
|
||||
search_words.update(re.split(r'\s+', main_value_normalized))
|
||||
|
||||
# Собираем слова из синонимов метаданных
|
||||
metadata_synonyms = metadata_dict.get(KEY_SYNONYM) or []
|
||||
metadata_synonyms = metadata_dict.get(KEY_SYNONYM_EN) or []
|
||||
for synonym in metadata_synonyms:
|
||||
# Применяем супер-нормализацию к каждому синониму
|
||||
syn_normalized = super_normalize_string(synonym)
|
||||
@@ -429,7 +429,7 @@ def build_search_report(
|
||||
|
||||
# Получаем метаданные и синонимы
|
||||
dup_metadata = getattr(dup, metadata_field_name) or {}
|
||||
dup_synonyms = dup_metadata.get(KEY_SYNONYM) or []
|
||||
dup_synonyms = dup_metadata.get(KEY_SYNONYM_EN) or []
|
||||
|
||||
# Ищем слово в основном поле и синонимах (case-insensitive)
|
||||
found_locations = []
|
||||
@@ -667,7 +667,7 @@ def validate_entity_for_admin_form(
|
||||
remove_conflicting_synonyms_from_duplicates(
|
||||
duplicates_queryset,
|
||||
metadata_field_name,
|
||||
metadata_dict.get(KEY_SYNONYM) or [], # Удаляем все синонимы текущей записи
|
||||
metadata_dict.get(KEY_SYNONYM_EN) or [], # Удаляем все синонимы текущей записи
|
||||
)
|
||||
# Выходим без ошибки в админку, т.к. пользователь "проверил и уверен!"
|
||||
# Конфликтующие синонимы удалены, запись сохранится нормально
|
||||
@@ -679,7 +679,7 @@ def validate_entity_for_admin_form(
|
||||
# Для каждого синонима текущей записи ищем, в каких записях он есть
|
||||
|
||||
# Собираем текущие синонимы с нормализацией
|
||||
current_synonyms_list = metadata_dict.get(KEY_SYNONYM) or []
|
||||
current_synonyms_list = metadata_dict.get(KEY_SYNONYM_EN) or []
|
||||
|
||||
# Строим словарь: {нормализованный синоним: {оригинальный синоним, запись1, запись2, ...}}
|
||||
synonym_to_records = {}
|
||||
@@ -694,7 +694,7 @@ def validate_entity_for_admin_form(
|
||||
# Ищем этот синоним в метаданных других записей
|
||||
for dup in duplicates_queryset:
|
||||
dup_metadata = getattr(dup, metadata_field_name) or {}
|
||||
dup_synonyms = dup_metadata.get(KEY_SYNONYM) or []
|
||||
dup_synonyms = dup_metadata.get(KEY_SYNONYM_EN) or []
|
||||
|
||||
# Проверяем: есть ли текущий синоним в синонимах этой записи
|
||||
for dup_syn in dup_synonyms:
|
||||
|
||||
@@ -317,7 +317,8 @@ LOGGING = {
|
||||
SLUG_MAX_LENGTH = 60
|
||||
|
||||
# Ключи для типовых параметров в мета-полях (для TbLabel, TbSeller, TbArtist, TbMusicStyle и т.д.)
|
||||
KEY_SYNONYM = 'SYNONYM'
|
||||
KEY_SYNONYM_EN = 'SYN_EN' # Ключ для хранения синонимов на английском языке (для поиска по синонимам) и ДЛЯ ПАРСЕРОВ
|
||||
KEY_SYNONYM_RU = 'SYN_RU' # Ключ для хранения синонимов на русском языке (для представления на фронтенд)
|
||||
|
||||
# ДЛЯ ВАЛИДАЦИИ (поиска похожих исполнителей, стилей и т.д. (используется в TbLabel.matching_type, TbSeller.matching_type и т.д.)
|
||||
VALIDATE_KEY__MATCH_TYPE = 'MATCH_TYPE'
|
||||
|
||||
Reference in New Issue
Block a user