如何为未知属性设置Django模型架构?

H C*_*H C 0 django django-models django-queryset

我有一个人物模型。

class Person(models.Model):
    name_first = models.CharField(max_length=100)
    name_middle = models.CharField(max_length=100, null=True, blank=True)
    name_last = models.CharField(max_length=100)
    date_birth = models.DateField(null=True, blank=True)
    date_death = models.DateField(null=True, blank=True)
Run Code Online (Sandbox Code Playgroud)

我正在尝试将其扩展到音乐界的不同角色:作曲家,表演者和赞助人。

一个人可以是一个,两个或所有三个角色。如果某人是表演者,我还需要为该人分配一种或多种乐器。在实例化时,您可能不知道某人是否是表演者。否则他们的角色会随着时间而改变。

我希望能够搜索并显示一个人(如果他是三个人)既是作曲家,钢琴家又是赞助人。例如:贝多芬是指挥,作曲家和钢琴家。

我对实现的最初想法是继承Person类。

class Composer(Person):
    pass

class Performer(Person):
    instrument = models.ManyToManyField(Instrument, verbose_name=_('instrument'), blank=True,)

class Patron(Person):
    pass

class Instrument(models.Model):
    name = models.CharField(max_length=100, null=True, blank=True)
Run Code Online (Sandbox Code Playgroud)

问题1:我应该改用某种抽象模型吗?如果是这样,我将如何处理?

问题2:我如何寻找一个人,并知道他们是否是作曲家,赞助人和/或表演者,以及他们是哪种表演者。

谢谢。

ino*_*tia 7

我的方法是:定义一个基Person类,并使其他模型对该模型具有外键。

首先,创建您的Person课程。

class Person(models.Model):
    name_first = models.CharField(max_length=100)
    name_middle = models.CharField(max_length=100, null=True, blank=True)
    name_last = models.CharField(max_length=100)
    date_birth = models.DateField(null=True, blank=True)
    date_death = models.DateField(null=True, blank=True)

    @property
    def is_performer(self):
       return hasattr(self, 'performer_role')

    @property
    def is_patron(self):
        return hasattr(self, 'patron_role')

    @property
    def is_composer(self):
        return hasattr(self, 'composer_role')

    @property
    def roles(self):
        roles = []
        if self.is_performer:
            roles.append('performer')
        if self.is_patron:
            roles.append('patron')
        if self.is_composer:
            roles.append('composer')
        return roles
Run Code Online (Sandbox Code Playgroud)

其次,创建您的特定模型并为该人员设置外键。

class ComposerRole(models.Model):
    person = models.OneToOneField(Person, on_delete=models.CASCADE, related_name='composer_role')
    # other fields as necessary

class PerformerRole(models.Model):
    person = models.OneToOneField(Person, on_delete=models.CASCADE, related_name='performer_role')
    instrument = models.CharField(max_length=100, blank=True)
    performer_type = models.CharField(max_length=100, blank=True) //conductor, performer
    # other fields as necessary

class PatronRole(models.Model):
    person = models.OneToOneField(Person, on_delete=models.CASCADE, related_name='patron_roll')
    # other fields as necessary
Run Code Online (Sandbox Code Playgroud)

要实例化具有正确角色的新人,您可以像这样添加他们:

p = Person.objects.create(...)
PerformerRole.objects.create(person=p, instrument='...')
Run Code Online (Sandbox Code Playgroud)

要检查某人是否有角色,只需执行person_instance.is_performer。要获取该角色的数据,请执行person_instance.performer_role.instrument

这种方法的另一个好处是,它允许您查询作曲家,顾客和表演者,例如ComposerRole.objects.all()ComposerRole.objects.filter(person__last_name='Beethoven')

希望能有所帮助。

编辑:添加rolesPerson。这样,您就可以通过一个人获得所有角色person_instance.roles

  • 利用具体类的继承,您将无法创建具有所有三个角色的“人”。当您在数据库中创建`Composer`时,它将在`Person`表**和** Composer`表中创建具有相同ID的唯一行。但是您将无法为同一个人设置“ Performer”。类继承不能为您做到这一点。 (2认同)