Managing Django Model Class for Workout Application

Question:

I am building up a workout progress application for a learning project. When setting the class model for the project I came across to schools of thought and I don’t know what is the advantages and disadvantages for reach.

Here is the simply version:

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)

and the second more complicated is:

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)
            + " "
        )

The requested project outcome is to just to set the progress of the workout logging the weight and reps of each excercise.

My question is which is the more preferred and why should each model be used?

Asked By: A_K

||

Answers:

Your first example is a 1:n (I read it 1 to n) relationship

(exercise) 1 <-> n (sets)

Every Exercise instance can be associated with an arbitrary number of Set instances. But Every set is associated with exactly 1 instance of Exercise.

As I understood your requirements that will totally do the job.

Your second example is a bit complicated, so I will try to break it down.

(exercise) 1 <-> n (exerciseset) <-> n (sets)

Every Exercise instance can be associated with an arbitrary number of ExerciseSet instances. But Every ExerciseSet is associated with exactly 1 instance of Exercise (all via the .exercise variable of ExerciseSet.

Furthermore each ExerciseSet can be connected to an arbitrary amount of Sets while each Set can also be part of multiple (n:n) ExerciseSet.

Since this is a rather complicated structure I am sure what you tried to achieve was an n:n relation ship with a through model.

(exercises) n <-> n (sets)

Now this allows every Exercise to have multiple sets while each set can be part of an arbitrary amount of exercises. This can be achieved by the simple use of a ManyToManyField on any of the models.

The way how the ManyToMany or n:n relation works is by creating a third table which has a column for each model saving the primary keys, such that each row in that table stores the connection of one exercise and one set. This table is hidden.

Now, it is possible to add the through param to the ManyToManyField. This allows to explicitly set that table using a through model, aka intermediary model, see documentation. This model allows you to not only connect both models but add additional information.

I.e. it would be possible to not only let Exercises have an arbitrary amount of Sets, but you could also store the information on how often (some count) that particular set is part of that exercise, or how much time there is for that particular set (without creating a new set), such that the set itself (n:n) can be part of multiple Exercises in different setups, without creating new sets all the time… just writing thoughts here.

The best example for n:n is still the Club <-> User relation, where the intermediate model Membership helps to store which User is in which Club, since a User can be in multiple Clubs and a Club can have multiple User. The Membership could additionally store the information when the user joined the club, or what grade the membership is.

Answered By: coderiot
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.