gpt4 book ai didi

django - 外键中的许多模型

转载 作者:行者123 更新时间:2023-12-04 04:01:23 26 4
gpt4 key购买 nike

假设我有一个模型,员工:

员工

  • 名称:CharField
  • 电子邮件:EmailField
  • 类型:外键

问题出在 type 字段上。我希望外键能够是几种不同类型的模型。例如,一个用于 Software Developer,另一个用于 Janitor,等等。

我可以通过为所有类型设置一个外键字段并将许多设置为空来做到这一点,但这似乎很糟糕。这有意义吗?

我怎样才能做到这一点?谢谢!!

最佳答案

有很多方法可以将这种级别的多态性建模到这样的场景中。

选项 1 - 混凝土基础模型

包括一个 employee_type 字段,指示正在使用的具体模型。

class Employee(models.Model):
name = models.CharField(max_length=50)
email = models.CharField(max_length=80)
employee_type = models.CharField(max_length=20)

class Janitor(Employee):
[...]

class SoftwareEngineer(Employee):
[...]

所有相互属性都可以存储在Employee 模型中。

一旦具体类(软件工程师、看门人等)被实例化,它将继承其父类的所有属性。

设置和使用 employee_type 您可以区分创建了哪个具体类。

有关这方面的更多信息,请参见 here

[更新]

使用 django Signal 可以导出具体的类名并将其与关联的实例一起存储。

信号.py

from django.db.models.signals import pre_save

def store_classname(sender, instance, **kwargs):
instance.employee_type = instance.__class__.__name__

for subclass in Employee.__subclasses__():
pre_save.connect(store_classname, sender=subclass)

这确保每次都存储正确的标识符。

现在在您想要选择要使用的具体类类型的 View 中,您可以在如下情况下继续使用它:

views.py

#EXAMPLE USAGE
employee = Employee.objects.get(id=1)
if employee.employee_type == 'Janitor':
employee = Janitor.objects.get(id=employee.id)

或者通过使用模型名称和对全局变量的查找来动态派生它。

#EXAMPLE USAGE
from <you_app>.models import *
def get_class(classname):
cls = globals()[classname]
return cls

employee = Employee.objects.get(id=1)
concrete_employee = get_class(employee.employee_type)
[...]

注意:更改父模型或子模型的名称时要小心,因为这会影响使用旧模型名称的历史记录。要解决此问题,请使用 django 的 update()bulk_update 函数将所有旧名称转换为新名称。更多信息是 here

选项 2 - django-polymorphic

使用名为 django-polymorphic 的 django 包,这允许在查询父类时返回所有具体类。

模型.py

from polymorphic.models import PolymorphicModel

class Employee(PolymorphicModel):
EMPLOYEE_TYPE_CHOICES = (
('Janitor', 'Janitor'),
('Software Engineer', 'Software Engineer'),
)
name = models.CharField(max_length=50)
email = models.CharField(max_length=80)

class Janitor(Employee):
[...]

class SoftwareEngineer(Employee):
predominant_programming_language= models.CharField(max_length=100)
[...]

Employee 模型上查询时,将返回以下内容

>>> Employee.objects.filter(id=1)
[ <Employee: id 1, name "Joe Bloggs", email "example@example.com">,
<SoftwareEngineer: id 1, name "Joe Bloggs", email "example@example.com", predominant_programming_language "Python">,]

关于django - 外键中的许多模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63019628/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com