正确构建Django模型

时间:2012-05-08 20:40:29

标签: django model

我正在为锻炼创建一个跟踪应用程序,我想知道创建模型的最有效方法。我做的大多数练习都有重复,组合和重量。但是有一些有距离和时间的跑步。起初,我打算创建两个不同的模型来捕获每个模型,但后来我觉得组合起来可能会更好。现在,我不确定。

好的,下面是我的第一遍:

LEVELS = (
    (1, '1 - Hardly'),
    (2, '2'),
    (3, '3'),
    (4, '4'),
    (5, '5 - Average'),
    (6, '6'),
    (7, '7'),
    (8, '8'),
    (9, '9'),
    (10, '10 - Very'),

class Jog(models.Model):
    distance = models.DecimalField("Distance (Miles)", max_digits=4, decimal_places=2)
    time = models.DecimalField("Time (Minutes)", max_digits=4, decimal_places=2)
    intensity = models.IntegerField("Intensity", choices = LEVELS, default = 5)
    date = models.DateTimeField("Date", blank=True, default=datetime.now)   
    notes = models.TextField("Notes", blank=True)

    def __str__(self):
        return "%s Miles in %s Minutes (Intensity of %s)" % (self.distance, self.time, self.intensity)

    class Meta:
        verbose_name = "Jog"

class Exercise_Type(models.Model):
    name = models.CharField("Exercise Name", max_length=200, unique = True)
    slug = models.SlugField(max_length=100, blank=True)
    notes = models.TextField("Notes", blank=True)

    def __str__(self):
        return self.name

class Workout(models.Model):
    exercise_type = models.ForeignKey(Exercise_Type, verbose_name="Exercise Type")
    reps = models.IntegerField("Repetitions")
    sets = models.DecimalField("Sets", max_digits=2, decimal_places=1)
    weight = models.IntegerField("Weight", blank=True, null=True)
    intensity = models.IntegerField("Intensity", choices = LEVELS, default = 5)
    date = models.DateTimeField("Date", blank=True, default=datetime.now)
    notes = models.TextField("Notes", blank=True)

这看起来很愚蠢,因为慢跑是一种锻炼方式,因为它具有不同的测量特征而只能被分开。那么我想,如果我做这样的事情怎么办?在锻炼类型中定义必要的字段,然后通过询问用户锻炼类型来启用/禁用它们:

class Exercise_Type(models.Model):
    name = models.CharField("Exercise Name", max_length=200, unique = True)
    slug = models.SlugField(max_length=100, blank=True)
    notes = models.TextField("Notes", blank=True)

    distance = models.BooleanField("Use Distance Field?", default = False)
    time = models.BooleanField("Use Time Field?", default = False)
    reps = models.BooleanField("Use Reps Field", default = False)
    sets = models.BooleanField("Use Sets Field?", default = False)
    weight = models.BooleanField("Use Weight Field?", default = False)

    def __str__(self):
        return self.name

class Workout(models.Model):
    exercise_type = models.ForeignKey(Exercise_Type, verbose_name="Exercise Type")
    distance = models.DecimalField("Distance (Miles)", max_digits=4, decimal_places=2, blank = True, null=True)
    time = models.DecimalField("Time (Minutes)", max_digits=4, decimal_places=2, blank = True, null=True)
    reps = models.IntegerField("Repetitions", blank = True, null=True)
    sets = models.DecimalField("Sets", max_digits=2, decimal_places=1, blank = True, null=True)
    weight = models.IntegerField("Weight", blank=True, null=True)
    intensity = models.IntegerField("Intensity", choices = LEVELS, default = 5)
    date = models.DateTimeField("Date", blank=True, default=datetime.now)
    notes = models.TextField("Notes", blank=True)

这似乎是浪费资源,因为无论是否需要,每项练习在技术上都会占据各个领域。

然后我想,子分类怎么样?就在那时我放弃了,并决定吸引那些比我更有知识的人。

组织此模型的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

由于每个练习都有一个或多个要测量的属性,因此您应该提取这些属性,因此最终会得到三个主要模型。

class Metric(models.Model):
   name = models.CharField(max_length=20)
   description = models.TextField(null=True, blank=True)
   measured_in = models.CharField(max_length=20, null=True, blank=True)
   # other fields

class Measurement(models.Model):
   metric = models.ForeignKey(Metric)
   value = models.CharField(max_length=20, null=True, blank=True)
   workout_date = models.DateField(auto_now=True)

class Workout(models.Model):
   # common attributes for each workout
   name = models.CharField(max_length=200)
   notes = models.TextField()
   metrics = models.ManyToManyField(Measurement)

您可以向Metric添加各种指标(您衡量的内容)。对于每个锻炼,您可以通过添加创建新Measurement来确定要跟踪的指标。最后,您在创建它时将其与每个锻炼相关联。

以下是一个示例:

reps = Metric.objects.create(name='Reps')
my_reps = Measurement.objects.create(metric=reps,value=10)
w = Workout(name="Weights")
w.metrics.add(my_reps)
w.save()

答案 1 :(得分:1)

这正是继承的目的。创建一个通用的Workout类型,然后将其与运动类型子类化。使用子类上的唯一/特定属性。

class Workout(models.Model):
    date = models.DateTimeField("Date", blank=True, default=datetime.now)
    notes = models.TextField("Notes", blank=True)

class Jog(Workout):
    distance = models.DecimalField("Distance (Miles)", max_digits=4, decimal_places=2, blank = True, null=True)
    time = models.DecimalField("Time (Minutes)", max_digits=4, decimal_places=2, blank = True, null=True)

class Weightlifting(Workout):
    reps = models.IntegerField("Repetitions", blank = True, null=True)
    sets = models.DecimalField("Sets", max_digits=2, decimal_places=1, blank = True, null=True)
    weight = models.IntegerField("Weight", blank=True, null=True)

等等。如果您不需要在任何地方使用通用Workout类型,则可以将其设置为抽象模型。