Django 模型继承与 OneToOne 字段
Django Model Inheritance versus OneToOne field
编辑:两种方法的优点和缺点。
所以,
我有三个模型:人、客户、成员
Person 是基本模型,Client 和 Member 是 Person 的配置文件。
class Person(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
verbose_name=_('email address'),
max_length=255,
unique=True,
)
class Client(User): #or maybe models.Model and explicit OneToField
first_name = models.CharField(verbose_name=_('first name'), max_length=30)
last_name = models.CharField(verbose_name=_('last name'), max_length=30)
class Member(User): #or maybe models.Model and explicit OneToField
description = models.CharField(verbose_name=_('first name'), max_length=255)
# other stuff
那么,我想要什么?
在管理员中,当我们添加客户或成员时,我想填写电子邮件字段(来自基础 class 的字段),就好像它在派生 class 中一样。例如,在管理中 list_display = ('email', 'first_name')。不是 select 个用户框。
Person class 可以单独实例化,"attached" 到创建的配置文件。比如person=Person(email="test@gmail.com"), client=Client(person=person,first_name="test"...)。特别是,这应该以表格形式工作。当用户(人)通过身份验证时,我想提供填写个人资料(客户)表格并将人员附加到此表格的能力。
一个人可以同时拥有两个账户。如果我删除client/member,对应的人应该不会被删除
第三个选项其实不是必须的,但知道怎么做对我很有用。
所以,方案一是通过继承完美解决的,Person
就是User
,但是当方案二实现时,这种方式就失效了。由于Person
和Client
被认为是一个整体,我无法附加用户,重复键错误。
选项 2 通过扩展 models.Model 并附加 person=models.OnetoOneField(Person,primary_key=True)
解决。但是,管理员坏了(第一个选项),因为客户端没有像电子邮件这样的字段。
那么,要采取什么方法来解决以上问题呢?
有没有简单的方法?
如果没有简单的方法,是否有高级方法,如重写元class、对象描述符或编写自定义 OneToOne 字段?
欢迎提出任何建议。
谢谢。
您可以为此使用 post_delete
signal。
所以你会:
- 在两个模型上注册
post_delete
信号
- 一个删除,检查另一个对象是否存在,然后删除。
Whosebug 上有很多关于 post_delete
信号实现的示例,所以我将省略该部分。
编辑:两种方法的优点和缺点。 所以, 我有三个模型:人、客户、成员 Person 是基本模型,Client 和 Member 是 Person 的配置文件。
class Person(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
verbose_name=_('email address'),
max_length=255,
unique=True,
)
class Client(User): #or maybe models.Model and explicit OneToField
first_name = models.CharField(verbose_name=_('first name'), max_length=30)
last_name = models.CharField(verbose_name=_('last name'), max_length=30)
class Member(User): #or maybe models.Model and explicit OneToField
description = models.CharField(verbose_name=_('first name'), max_length=255)
# other stuff
那么,我想要什么?
在管理员中,当我们添加客户或成员时,我想填写电子邮件字段(来自基础 class 的字段),就好像它在派生 class 中一样。例如,在管理中 list_display = ('email', 'first_name')。不是 select 个用户框。
Person class 可以单独实例化,"attached" 到创建的配置文件。比如person=Person(email="test@gmail.com"), client=Client(person=person,first_name="test"...)。特别是,这应该以表格形式工作。当用户(人)通过身份验证时,我想提供填写个人资料(客户)表格并将人员附加到此表格的能力。
一个人可以同时拥有两个账户。如果我删除client/member,对应的人应该不会被删除
第三个选项其实不是必须的,但知道怎么做对我很有用。
所以,方案一是通过继承完美解决的,Person
就是User
,但是当方案二实现时,这种方式就失效了。由于Person
和Client
被认为是一个整体,我无法附加用户,重复键错误。
选项 2 通过扩展 models.Model 并附加 person=models.OnetoOneField(Person,primary_key=True)
解决。但是,管理员坏了(第一个选项),因为客户端没有像电子邮件这样的字段。
那么,要采取什么方法来解决以上问题呢? 有没有简单的方法? 如果没有简单的方法,是否有高级方法,如重写元class、对象描述符或编写自定义 OneToOne 字段?
欢迎提出任何建议。
谢谢。
您可以为此使用 post_delete
signal。
所以你会:
- 在两个模型上注册
post_delete
信号 - 一个删除,检查另一个对象是否存在,然后删除。
Whosebug 上有很多关于 post_delete
信号实现的示例,所以我将省略该部分。