1

可以说我有以下形式的课程:

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

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

b = B()

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

4

2 回答 2

2

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

b.__class__=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)

And here are my tests:

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)

Result of the test is OK.

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

于 2013-11-14T02:32:14.947 回答
-3

b = C() 将使局部变量 b 成为 C 类的实例。不知道你为什么要这样做。您可以发布更多代码吗?

于 2013-11-14T02:22:54.540 回答