【问题标题】:Django: Accessing child class of an abstract modelDjango:访问抽象模型的子类
【发布时间】:2010-10-28 16:57:57
【问题描述】:

我有几个从一个基类继承的用户配置文件模型,如下所示:

class BaseProfile(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=100)
    ...
    class Meta:
        abstract = True

class DoctorProfile(BaseProfile):
    license_no = models.CharField(max_length=10)
    ...

class PharmacistProfile(BaseProfile):
    pass

当我有一个用户实例时,我想获取他们的个人资料。

我不想一一检查用户是否有个人资料。像这样:

if user.doctorprofile_set.all().count() == 1:
    return user.doctorprofile_set.all()[0]
elif user.pharmacistprofile_set.all().count() == 1:
    return user.pharmacistprofile_set.all()[0]
...

每个配置文件都是最好的方法,因为它不是 DRY 并且需要对数据库进行额外查询。

最好的方法是什么?

编辑: 最好在设置中定义 AUTH_PROFILE_MODULE 以指向像 AUTH_PROFILE_MODULE = 'profiles.baseprofile' 这样的基本模型,并能够对每个具有不同配置文件类的用户使用 user.get_profile() 从相同的基本配置文件。

【问题讨论】:

  • 我能问一下您为什么选择使用继承而不是组合或聚合作为划分不同类型用户的方式吗?为什么带有“is_a”标志的单个配置文件类不是正确的方法?然后你可以使用 get_profile() 做一件事。
  • 我提供的例子是一个简化的例子。在实际情况下,大约有 10 种不同的配置文件类型,它们具有许多常见和不常见的属性。为了保持模型 DRY,继承对我来说似乎更自然。即使我使用了组合,我相信在尝试获取用户的个人资料时我仍然会遇到同样的问题,不是吗?

标签: django inheritance abstract-class


【解决方案1】:

将其设为 OneToOneField 而不是 FK,然后执行 user.doctorprofile 等。不过,如果出现问题,OneToOne 将抛出 Foo.DoesNotExist 或 Foo.MultipleObjectsReturned,因此请准备好捕捉这些异常

【讨论】:

  • 谢谢,这会让事情变得更整洁。但是这种方法仍然需要逐个查询每个配置文件的可能性,这意味着对数据库的额外命中并且不是很干,因为如果引入了新配置文件,则应将另一个 try ... except 块添加到获取配置文件的代码中。在 BaseProfile 类上使用 get_profile() 会很好。我会更新我的问题。
  • 我没有说它是完美的。我收集到,在 1.3/1.4 之前,在 Django 中扩展用户模型不会变得更好。而且您总是可以添加一些代码(就像我一样),在第一次需要时缓存配置文件,然后在再次保存模型时使其密钥无效
  • 好吧,我从未来说,在 Django 1.9 之前,我们还没有任何东西接近它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 2011-08-16
  • 2018-08-23
  • 1970-01-01
  • 2011-08-05
  • 2021-05-09
  • 1970-01-01
相关资源
最近更新 更多