如何在Django中使用通用ForeignKey定义Mode

时间:2018-06-15 20:00:15

标签: django django-models foreign-keys multiple-choice

我是django的新手

我想用以下逻辑创建模型:

class ExerciseCardio(models.Model):
    pass


class ExerciseWeights(models.Model):
    pass


class Exercise(models.Model):
    name = models.CharField(max_length=100, default='')

    EXERCISE_TYPE_CHOICES = (
        (1, 'cardio'),
        (2, 'Weights'),
    )

    exercise_type = models.PositiveSmallIntegerField(
        choices=EXERCISE_TYPE_CHOICES, default=2)

    if exercise_type == 1:
        exercise_model_type = models.ForeignKey(ExerciseCardio, on_delete=models.CASCADE, default=0)
    elif exercise_type == 2:
        exercise_model_type = models.ForeignKey(ExerciseWeights, on_delete=models.CASCADE, default=0)

    def __str__(self):
        return self.name

我知道它看起来很难看 但必须有办法做到这一点

2 个答案:

答案 0 :(得分:1)

是的,有一种方法:你可以使用djangos generic relations

它的要点如下:

from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

class Exercise(models.Model):
    EXERCISE_TYPE_CHOICES = (
        (1, 'cardio'),
        (2, 'Weights'),
    )

    name = models.CharField(
        max_length=100, default='')
    exercise_type = models.PositiveSmallIntegerField(
        choices=EXERCISE_TYPE_CHOICES, default=2)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

在您看来,在创建Exercise实例时,您必须选择正确模型的ContentType,可能是这样的:

obj = Exercise()
obj.exercise_type = ...
if obj.exercise_type == 1:
    obj.content_type = ContentType.objects.get_for_model(ExerciseCardio)
else:
    obj.content_type = ContentType.objects.get_for_model(ExerciseWeights)

答案 1 :(得分:0)

正如您所指出和Ralf所说明的那样,Django中的实际通用外键仍然很笨拙。

但是,您所谈论的是一些需要以特定方式运行的特定类型,并且我认为在django-model-utils.managers.InheritanceManager库的自定义管理器的帮助下,这是继承的一个不错的选择。 / p>

Integer

models.py

示例(在Django shell中,带有我喜欢的测试应用from django.db import models from model_utils.managers import InheritanceManager class Exercise(models.Model): name = models.CharField(max_length=32) objects = InheritanceManager() def __str__(self): return "{n} ({t})".format(n=self.name, t=type(self)) class ExerciseCardio(Exercise): pass class ExerciseWeights(Exercise): pass ):

eh