关于python:在Django的基础模型中”创建”子模型

“Create” child model from base model in django

我有三个模型,一个称为CommonUser(AbstractUser)的基础,两个子Professional(CommonUser)Client(CommonUser)

我正在使用django-rest-social-auth从Facebook,Google等创建用户,在我的设置中,我设置了AUTH_USER_MODEL = 'users.CommonUser',但是我有两个步骤来创建用户,首先使用社交登录之后,此后,我有了一个表单来填充来自某种类型用户的其余数据。

我现在需要从django-rest-social-auth创建的CommonUser创建一个Client或Professional实例,换句话说,我要"移动"由django-rest-social创建的CommonUser实例提交第二步表单后,对客户端实例或Professional实例进行-auth。


经过一些测试和相关搜索,我找到了解决方法。

在我的情况下,在保存客户端或专业版用户的视图中,我将使用:

1
2
3
common_user = CommonUser.objects.get(id=id)
common_user.__class__ = Client
common_user.save()

编辑

上面的方法在本次讨论中看起来是不安全的。

更多搜索,我在这里找到了解决方法

基本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class CommonUser(AbstractUser):
    # attributes...

    @classmethod
    def create_child(cls, child_class, attrs):
       """
        Inputs:
        - child_class: child class prototype
        - attrs: dictionary of new attributes for child
       """

        try:
            id = attrs.pop('id', None)
            common_user = CommonUser.objects.get(id=id)
        except Exception as e:
            raise e
        parent_link_field = child_class._meta.parents.get(common_user.__class__, None)
        attrs[parent_link_field.name] = common_user
        for field in common_user._meta.fields:
            value = getattr(common_user, field.name)
            if value:
                attrs[field.name] = value
        s = child_class(**attrs)
        s.save()
        return s


class Professional(CommonUser):
    # attributes...


class Client(CommonUser):
    # attributes...

现在我可以执行:

1
2
>>> professional = CommonUser.create_child(Professional, {'id': 1})
>>> client = CommonUser.create_child(Client, {'id': 2})