首页 > 解决方案 > 如何在 Django 中使用通用 ForeignKey 定义模式

问题描述

我是 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

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

标签: djangodjango-modelsforeign-keysmultiple-choice

解决方案


是的,有一种方法:你可以使用 djangos 的泛型关系

它的要点如下:

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)

推荐阅读