【问题标题】:Django - Many to Many Relationship with Workouts & ExercisesDjango - 与锻炼和练习的多对多关系
【发布时间】:2021-12-03 09:49:30
【问题描述】:

我目前不知道如何执行以下操作:

我想跟踪锻炼并查看锻炼的进度。

每次锻炼都有名称、体重、日期和锻炼。

我想在添加锻炼时选择锻炼(锻炼已经预先创建了名称和一些标签),但是,每次锻炼都不同,这意味着锻炼的次数、组数和重量每次都不同.

我不确定如何为此制作模型。

我添加了一张我制作的简单设计的图片,以展示我所追求的

希望有人可以帮助我,我很确定这是一个简单的解决方案,但是我的大脑卡在了 atm 上。

Image Of Design

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    首先,我建议通读 Django models docs 以了解模型代表什么以及它们是如何工作的。

    为了解决您的问题,我认为您已经正确识别了创建模型所需的所有信息,所以让我们逐步了解它们。

    架构

    退后一步思考应用中的实体会很有帮助。确定它们是什么,它们拥有什么属性以及这些属性中的哪些是atomic,即不能是它们自己的实体。

    • 锻炼 - 您提到要跟踪锻炼,每个锻炼都有名称、体重、日期和锻炼。除了 exercises 之外的所有这些属性似乎都是原子的,因为它们可以用基本数据类型(字符串、浮点数、日期时间等)表示。此外,一个锻炼可以有many exercises,表示我们需要将它抽象成它自己的实体。

    • 练习 - 您确定练习是预设的,需要有名称和标签。名称是我们可以用字符串表示的东西,但是一个练习可以有多个标签,这意味着它不是原子的(具有one-to-many 关系)。这意味着我们需要将其提取到自己的实体中。

    • 标签 - 根据您的说法,标签仅具有一个属性,该属性是可以用字符串表示的名称。一个标签可以属于多个练习。

    您可能想知道我们将每次锻炼的次数、组数和重量数据存储在哪里。这实际上需要一个额外的实体来存储运动和锻炼之间的多对多关系。我们称之为Workout-Exercise

    有了这些信息,我们可以画出Entity Relationship Diagram

    这为我们提供了开始创建 Django 模型所需的内容。

    型号

    让我们从ExerciseTag 实体开始。我们可以简单地将这些直接翻译成 Django 模型:

    from django.db import models
    
    
    class Tag(models.Model):
        name = models.CharField(max_length=200)
        
        
    class Exercise(models.Model):
        name = models.CharField(max_length=200)
        tags = models.ManyToManyField(Tag)
    

    在这里,我们创建了两个模型,并在 ExerciseTag 之间指定了多对多关系。这意味着一个Exercise 对象可以有许多Tag 对象,例如您可以调用exercise.tags.all() 来获取给定Exercise 对象的所有标签。

    当我们创建Workout-Exercise 实体时,棘手的部分就来了。当我们在 Django 中使用ManyToManyField 时,它通常会自动创建一个我们看不到的映射模型/表。但是,如果我们想要存储有关这些关系的额外信息(就像我们在用例中所做的那样),我们必须使用 through model

    在这个模型上,我们必须为我们要链接的模型定义两个外键以及我们想要存储的额外字段数据的数据类型。在这种情况下,外键是WorkoutExercise,额外的数据是repssetsweight。因此,模型定义可能如下所示:

    class WorkoutExercise(models.Model):
        workout = models.ForeignKey(
            'Workout',
            on_delete=models.CASCADE,
        )
        exercise = models.ForeignKey(
            Exercise,
            on_delete=models.CASCADE,
        )
        reps = models.IntegerField()
        sets = models.IntegerField()
        weight = models.DecimalField(max_digits=5, decimal_places=2)
    
    
    class Workout(models.Model):
        name = models.CharField(max_length=200)
        body_weight = models.DecimalField(max_digits=5, decimal_places=2)
        date = models.DateTimeField(auto_now_add=True)
        exercises = models.ManyToManyField(
            Exercise,
            through=WorkoutExercise
        )
    

    如果您对我推荐的任何模型数据类型选择感到困惑,请查看Django model docs

    通过此设置,您应该能够访问和插入您需要的所有数据。如果您需要有关如何访问任何多对多关系数据的更多信息,请查看 Django many-to-many docs

    来源

    【讨论】:

      猜你喜欢
      • 2011-06-02
      • 2015-07-05
      • 2011-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-20
      • 2014-05-16
      • 2012-02-26
      相关资源
      最近更新 更多