Django模型继承与OneToOne字段 [英] Django Model Inheritance versus OneToOne field

查看:98
本文介绍了Django模型继承与OneToOne字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑:两种方法的优点和缺点。
SO,
我有三个模型:Person,Client,Member
Person是一个基本模型,Client和Member是Person的个人资料。




email = models.EmailField(
verbose_name = _('email address'),
max_length = $(

max_length = 255,
unique = True,


类客户端(用户):#or也可以是models.Model和显式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也许是model.Model和显式的OneToField
description = models.CharField(verbose_name = _('first name'),max_length = 255)
#其他东西

所以,我想要什么?


  1. 在管理员中,当我们添加客户端或成员时,我想填写字段电子邮件(基类中的字段),就像它在派生中一样d班。例如,在admin list_display =('email','first_name')中。没有为用户选择框。


  2. Person类可以单独实例化,并附加到创建的profiel。像person = Person(email =test@gmail.com),client = Client(person = person,first_name =test...)。特别是,这应该以形式工作。当用户(个人)进行身份验证时,我想提供填写个人资料(客户)表单的能力,并将个人附加到此表单。


  3. 一个人可以同时拥有账户。如果我删除客户/成员,则不应删除相应的人员。


第三选项实际上没有必要,但是对于我来说,知道如何做到这一点很有用。



所以选项1完全通过继承来解决, Person 用户,但是当实现选项2时,此方法失败。由于 Person 客户端被视为一个整体,我无法附加用户,重复键错误。



选项2通过扩展模型解决。模型和追加 person = models.OnetoOneField(Person,primary_key = True)。但是,管理员被破坏(第一选项),因为客户端没有电子邮件等字段。



那么为了解决上述问题,采取什么方法?
有简单的方法吗?
如果没有简单的方法,有没有高级的方法,比如覆盖元类,对象描述符或编写自定义OneToOne字段?



欢迎任何建议。 p>

谢谢。

解决方案

您可以使用 post_delete 信号



所以你会:




  • 注册 post_delete 两个模型

  • 一个删除,检查另一个对象是否存在,然后删除。



有很多关于在StackOverflow上执行 post_delete 信号的示例,所以我将把该部分留下。


EDIT: Advantages and disadvantages of both methods. SO, I have three models: Person, Client, Member Person is a base model, Client and Member are profiles for 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

So, what I want?

  1. In admin, when we add client or member, I want to fill field email (fields from base class) as if it was in derived class. For example, in admin list_display = ('email', 'first_name'). Not select boxes for user.

  2. Person class can be instantiated separately and the "attached" to the created profiel. Like person=Person(email="test@gmail.com"), client = Client(person=person,first_name="test"...). Especially, this should work in forms. When user (person) is authenticated I want to give ability to fill in profile (client) form and attach person to this form.

  3. One person can have both accounts. If I delete client/member, corresponding person should not be deleted.

3rd option actually is not necessary, but it is useful for me to know how to do it.

So, option 1 is perfectly solved by inheritance, Person is User, but this approach fails when option 2 is implemented. Since Person and Client are considered as one whole, I can't attach user, duplicate key error.

Option 2 is resolved by extending models.Model and appending person=models.OnetoOneField(Person,primary_key=True). However, admin is broken (1st option), because Client don't have fields like email.

So, what approach to take in order to solve above issues? Are there simple ways? If there are no simple ways, is there advanced way, like overriding metaclass, object descriptors or writing custom OneToOne field?

Any suggestions are welcomed.

Thank you.

解决方案

You can use the post_delete signal for this.

So you would:

  • Register the post_delete signals on both the models
  • One delet, check if the other object exists, and delete.

There are lots of examples on the implementation of post_delete signals on StackOverflow, so i will leave that part out.

这篇关于Django模型继承与OneToOne字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆