Рассмотрим игрушечный пример. Допустим, я разрабатываю онлайн-магазин автомобилей (нет). У каждой марки машины есть название, мощность двигателя и описание. При этом название и мощность двигателя интернациональны, а описание должно быть разное для разных языков. И мне надо всё это сохранить в SQL базу данных (скажем, MySQL).
Я придумал такую конструкцию:
Таблица автомобилей:
id (число)
name (строка)
power (число)
description_id (число)
Таблица переводов:
id (число)
lang_code (строка)
text (строка)
Соответственно, чтобы получить локализованное описание автомобиля, мы можем сделать запрос к таблице переводов, где id будет равен description_id, а lang_code будет равен нужному языку.
Особенности моей схемы: 1 таблица на все локализованные данные вообще. Можно добавить в таблицу автомобилей колонку localized_name_id, которая будет ссылаться на ту же таблицу переводов (но другую запись). Удалять автомобили тоже легко - нужно просто удалить все записи из таблицы переводов с соответствующим id. Также таблица переводов будет использоваться не только для таблицы автомобилей, но и, скажем, для таблицы кофеварок (у которых могут быть совсем другие наборы локализованных полей).
Таблица переводов, разумеется, имеет составной первичный ключ - id и lang_code (причём сначала идёт id).
А теперь два вопроса:
1) Насколько адекватно такое решение?
2) Как это уложить на ORM SQLAlchemy и Python? Если нет, то, возможно, ORM для других языков умеют такое (например, JPA в Java)? Или я хочу совсем странного?
UPD: Небольшая иллюстрация моего решения:
class Translation(db.Model):
id = db.Column(db.Integer, primary_key=True)
code = db.Column(db.String(2), primary_key=True)
text = db.Column(db.Text, nullable=False)
class Car(db.Model):
id = db.Column(db.String(64), primary_key=True)
name_id = db.Column(db.Integer)
name = db.relationship('Translation', primaryjoin=name_id == Translation.id, cascade='all, delete-orphan')
description_id = db.Column(db.Integer)
description = db.relationship('Translation', primaryjoin=description_id == Translation.id, cascade='all, delete-orphan')
power = db.Column(db.Integer)
С загрузкой, обновлением и удалением переводов проблем быть не должно, но вот с добавлением новых непонятно что будет.