Управление классом модели Django для приложения Workout
Я создаю приложение для выполнения учебного проекта. При определении модели класса для проекта я столкнулся со школами мысли, и я не знаю, какие преимущества и недостатки для достижения.
Вот простая версия:
class Exercise(models.Model):
name = models.CharField(max_length = 30)
def __str__(self):
return self.name
class Set(models.Model):
exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE, related_name='sets')
weight = models.FloatField(validators=[MinValueValidator(0)])
repetitions = models.IntegerField(validators=[MinValueValidator(1)])
def __str__(self):
return self.exercise.name + ' set #' + str(self.pk)
и второй более сложный:
class Exercise(models.Model):
# Attributes
name = models.CharField(null=False, blank=False, max_length=100)
# Methods
def __str__(self):
return self.name
class ExerciseSet(models.Model):
# Attributes for exercise sets
exercise = models.ForeignKey(Exercise, null=False, blank=False, on_delete=models.CASCADE)
sets = models.ManyToManyField("my_gym.Set", related_name="sets")
number_of_sets = models.IntegerField(null=False, blank=False, default=3)
# Methods
def __str__(self):
return str(self.exercise.name) + " - " + str(self.number_of_sets) + " sets"
class Set(models.Model):
# Attributes
reps = models.PositiveIntegerField(null=False, blank=False, default=0)
weight = models.DecimalField(max_digits=5, decimal_places=2)
# Methods
def __str__(self):
return (
str(self.reps)
+ " "
+ " x "
+ str(self.weight)
+ " "
)
Запрашиваемый результат проекта заключается в том, чтобы просто установить прогресс тренировки, регистрируя вес и повторения каждого упражнения.
Мой вопрос в том, какая модель является более предпочтительной и почему следует использовать каждую из них?
Ваш первый пример - это отношения 1:n (я читаю как 1 к n)
(упражнение) 1 <-> n (наборы)
Каждый экземпляр Exercise
может быть связан с произвольным числом экземпляров Set
. Но каждое множество ассоциируется ровно с 1 экземпляром Exercise
.
Как я понял ваши требования, это полностью выполнит работу.
Ваш второй пример немного сложен, поэтому я попробую разбить его на части.
(упражнение) 1 <-> n (набор упражнений) <-> n (наборы)
Каждый экземпляр Exercise
может быть связан с произвольным числом экземпляров ExerciseSet
. Но каждый ExerciseSet
связан ровно с 1 экземпляром Exercise
(все через переменную .exercise
из ExerciseSet
.
Более того, каждый ExerciseSet
может быть соединен с произвольным количеством Set
, а каждый Set
может быть частью множества (n:n) наборов упражнений.
Поскольку это довольно сложная структура, я уверен, что вы пытались достичь отношения n:n с помощью сквозной модели.
(упражнения) n <-> n (комплекты)
Теперь это позволяет каждому Упражнению иметь несколько наборов, при этом каждый набор может быть частью произвольного количества экзекуций. Это может быть достигнуто простым использованием ManyToManyField
на любой из моделей.
Способ работы отношения ManyToMany или n:n заключается в создании третьей таблицы, в которой есть столбец для каждой модели, сохраняющий первичные ключи, так что каждая строка в этой таблице хранит связь одного упражнения и одного набора. Эта таблица скрыта
Теперь можно добавить параметр through
к параметру ManyToManyField
. Это позволяет явно задать эту таблицу, используя сквозную модель, она же модель-посредник, см. документацию. Эта модель позволяет не только связать обе модели, но и добавить дополнительную информацию.
Т.е. можно не только позволить Exercise
s иметь произвольное количество Set
s, но и хранить информацию о том, как часто (некоторое количество) этот конкретный набор является частью этого упражнения, или сколько времени есть для этого конкретного набора (без создания нового набора), так что сам набор (n:n) может быть частью нескольких упражнений в разных установках, не создавая все время новые наборы... просто пишу мысли.
Лучшим примером для n:n по-прежнему является отношение Club
<-> User
, где промежуточная модель Membership
помогает хранить информацию о том, какой пользователь состоит в каком клубе, поскольку пользователь может состоять в нескольких клубах, а в клубе может быть несколько пользователей. Членство может дополнительно хранить информацию о том, когда пользователь вступил в клуб, или какого класса членство.