Я пытаюсь разработать приложение django, которое поможет отслеживать макро- и микроэлементы в моем рационе. Пока что я очень доволен документацией django. Но сейчас я застрял на более концептуальном вопросе, связанном с базами данных и связями моделей.
Моя текущая модель для Ингредиента и связанного NutrientProfile выглядит следующим образом:
class Ingredient(models.Model):
ingredient_id = models.UUIDField(
verbose_name="Ingredient",
primary_key=True,
default=uuid.uuid4,
editable=False,
)
name = models.CharField(max_length=300, unique=False)
synonyms = models.CharField(max_length=300, blank=True, null=True)
category = models.CharField(max_length=300, blank=True, null=True)
class NutrientProfile(models.Model):
nutrientProfileID = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False,
)
# Ingredient the NutrientProfile is associated to
ingredient = models.ForeignKey(
to="Ingredient",
related_name='nutrientProfile',
on_delete=models.CASCADE,
blank=True,
null=True,
)
fat_total = models.DecimalField(max_digits=7, decimal_places=4, blank=True, null=True)
protein = models.DecimalField(max_digits=7, decimal_places=4, blank=True, null=True)
cholesterol = models.DecimalField(max_digits=7, decimal_places=4, blank=True, null=True)
... more nutrients
Так что в настоящее время я могу создать Ингредиенты и связать их с одним или несколькими NutrientProfiles . Я не определял это отношение как «один-к-одному», потому что для одного ингредиента (нескольких источников данных) может быть несколько NutrientProfiles.
Теперь проблема: я понял, что мне потребуется дополнительная информация о каждое питательное вещество, такое как единица измерения, комментарий, дата добавления, ... Итак, я придумал следующие модели для включения таких деталей:
class NutrientProfile(models.Model):
NutrientProfileID = ... ID
ingredient = ... FK
fat_total = models.OneToOneField("Nutrient", on_delete=models.CASCADE)
protein = models.OneToOneField("Nutrient", on_delete=models.CASCADE)
cholesterol = models.OneToOneField("Nutrient", on_delete=models.CASCADE)
... more nutrients
class Nutrient(models.Model):
amount = models.DecimalField(max_digits=7, decimal_places=4, blank=True, null=True)
unit = models.CharField(max_length=5, choices=allowed_units)
comment = models.CharField(max_length=200)
...
Итак, каждое поле в NutrientProfile может содержать все необходимые данные в модели Nutrient . Имеет ли это смысл, или я иду в неправильном направлении? Было бы лучше хранить все детали в самом NutrientProfile ? Как и так?
class NutrientProfile(models.Model):
NutrientProfileID = ... ID
ingredient = ... FK
fat_total = models.OneToOneField("Nutrient", on_delete=models.CASCADE)
fat_total_amount = ...
fat_total_comment = ...
fat_total_unit = ...
protein = models.OneToOneField("Nutrient", on_delete=models.CASCADE)
protein_amount = ...
... more nutrients
Определение всех деталей вместе, мне кажется очень уродливым. Но размещение их в другой таблице значительно увеличит «работу» базы данных, верно? Для 10000 NutrientProfiles с каждыми 30 питательными веществами в таблице Nutrient уже будет 300000 строк. Разве это не было бы гораздо более неэффективно, чем просто хранить больше столбцов в таблице NutrientProfile ? Я использую PostgreSQL в качестве базы данных прямо сейчас.
А, на мой взгляд, более гибким способом работы с деталями было бы определение моделей NutrientProfile и Nutrient , например:
class NutrientProfile(models.Model):
NutrientProfileID = ... ID
ingredient = ... FK
# No defined nutrient fields
class Nutrient(models.Model):
nutrient_profile = models.ForeignKey('NutrientProfile', on_delete=models.CASCADE, null=False)
# Nutrient type. For example: fat, protein, cholesterol,...
# Maybe limited with predefined choices?
nutrient_type = models.CharField(max_length=50, choices=??)
amount = models.DecimalField(max_digits=7, decimal_places=4, blank=True, null=True)
unit = models.CharField(max_length=5, choices=allowed_units)
comment = models.CharField(max_length=200)
... more details
class Meta:
unique_together = ['nutrient_profile', 'nutrient_type']
Однако мой вопрос остается прежним. Является ли предпочтительным хранить больше полей в одной модели, или я должен разделить свои модели, даже если полученная таблица подробностей будет иметь больше строк? Как это влияет на производительность SQL?