在 Django 模型上更改孩子的类别 [英] Change class of child on django models

查看:19
本文介绍了在 Django 模型上更改孩子的类别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下形式的类:

Lets say I have classes in the form:

class A(models.Model):
   attrA = models.CharField()
class B(A):
   attrB = models.CharField()
class C(A):
   attrC = models.CharField()

然后我创建了一个 B 实例:

And then I create a instnace of B:

b = B()

现在,基于一些决定,我想将该对象 b 转换为 C 类的实例,但 attrC 属性可用.这可能吗?

Now, based on some decisions I wanted to transform that object b an instance of the C class but with the attrC attribute available. Is that possible?

推荐答案

在 python 中你可以像这样改变对象的类:

In python you can change class of an object like that:

b.__class__=C

那么 B 的所有属性都可用,即使它们没有为类 C 定义.尽管 b 现在是类 C 的实例,但它没有 C 的属性.在将对象保存到数据库(或调用 Model 类的其他方法)之前,您必须添加类 C 的所有剩余属性.为了证明它有效,我创建了一个简单的应用程序.这是我的模型:

Then all of B's attributes are available even when they are not defined for class C. Altough b is now instance of the class C it has no C's attributes. Before saving the object to database (or calling other methods of Model class) you have to add all remaining attributes of the class C. To prove it works I created a simple app. Here are my models:

class A(models.Model):
    attrA = models.CharField(max_length=128)
    class Meta:
        abstract=True
class B(A):
    attrB = models.CharField(max_length=128)
class C(A):
    attrC = models.CharField(max_length=128)

这是我的测试:

class ABCTestCase(TestCase):
    def test_changing_classes(self):
        """Changing classes"""
        a = A()
        self.assertIsInstance(a, A)
        a.attrA='bacon'
        self.assertEqual(a.attrA, 'bacon')
        a.__class__=B
        self.assertIsInstance(a, B)
        self.assertEqual(a.attrA, 'bacon')
        a.attrB='spam'
        self.assertEqual(a.attrA, 'bacon')
        self.assertEqual(a.attrB, 'spam')
        a.__class__=C
        self.assertIsInstance(a, C)
        self.assertIsInstance(a, A)
        self.assertNotIsInstance(a, B)
        a.attrC='egg'
        self.assertEqual(a.attrA, 'bacon')
        self.assertEqual(a.attrB, 'spam')
        self.assertEqual(a.attrC, 'egg')
        a.id=None
        a.save()
        self.assertIsNotNone(a.id)

测试结果正常.

更安全的方法是为每个从B转换为C或从C转换为B的类定义方法.

Safer approach is to define method for each class which convert from B to C or from C to B.

这篇关于在 Django 模型上更改孩子的类别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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