【问题标题】:How to write a peewee class that successfully initialises other peewee objects during its own initialisation?如何编写一个在自己初始化期间成功初始化其他 peewee 对象的 peewee 类?
【发布时间】:2018-06-02 15:51:56
【问题描述】:

我的课程是:

class B(Base_Model):
    b_attribute_1 = peewee.TextField(null=True)
    a = peewee.ForeignKey(A, null=True)

class A(Base_Model):
    a_attribute_1 = peewee.IntegerField(null=True)
    a_attribute_2 = peewee.DoubleField(null=True)
    class Meta:
        friend_server_address = "103.11.399.002"
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.save()
        from B import B
        # Option (1) -- semi-works: creates incomplete object b,
        #               a is initialised correctly.
        B.create(a=self)
        # Option (2) -- does not work: b is created successfully,
        #               a not created, giving KeyError = "ba1".
        # B.create(b_attribute_1 = kwargs["ba1"], a=self)
        return

我看到代码 cmets 中描述的问题(参见选项 1 和 2)的方式是测试代码:

class test_a_and_b(unittest.TestCase):
    def setUp(self):
        config.database.init("test.db")
        config.database.create_tables([A, B])
        A(a_attribute_1 = 9705,
          a_attribute_2 = 0.77,
          ba1 = "this is b")
        # This is the breakpoint where I study objects in memory.
        pdb.set_trace()
        return
    def tearDownModule()
        A.get().delete_instance(recursive=True, delete_nullable=True)  
        B.get().delete_instance(recursive=True, delete_nullable=True)
        config.database.drop_tables([A, B])
        os.remove("test.db")

因此,根据我在A__init__ 中选择的选项,我(在断点调用A.get()B.get() 之后)可以看到创建了完整的a 和不完整的b,或者只是完成b 和错误消息KeyError:"ba1"我想要的是创建两个完整的对象(数据库行)ab

我尝试查看 peewee 库,似乎他们的Model 使用了__new__,我没有看到任何__init__,所以也许这就是我的问题。在我的A 中尝试了不同的组合,但这似乎没有帮助。还尝试使用初始化,以编程方式定义属性和.save() 而不是.create()b,但这也没有帮助。

【问题讨论】:

    标签: python constructor orm peewee


    【解决方案1】:

    很确定您遇到的问题是,当您需要 A 的实例时,您并不总是包含 ba1。只有当您创建一个新实例时,您才会传入 ba1 .当您选择一个或当 peewee 在从 B 引用它时内部实例化一个时,您的 'ba1' 关键字参数将不存在,并且您的代码将失败并出现您遇到的错误。

    在使用之前检查“ba1”是否存在(因为只有在您自己明确创建新 A 时才会使用它)。换句话说,试试这个:

    import peewee
    import unittest
    
    database_proxy = peewee.Proxy()
    class BaseModel(peewee.Model):
        class Meta:
            database = database_proxy
    
    class A(BaseModel):
        a_attribute_1 = peewee.IntegerField(null=True)
        a_attribute_2 = peewee.IntegerField(null=True)
        def __init__(self, *args, **kwargs):
            super(A, self).__init__(*args, **kwargs)
            if "ba1" in kwargs:
                self.save()
                B.create(a=self, b_attribute_1 = kwargs["ba1"])
    
    class B(BaseModel):
        b_attribute_1 = peewee.TextField(null=True)
        a = peewee.ForeignKeyField(A, null=True)
    
    class test_a_and_b(unittest.TestCase):
        def setUp(self):
            db = peewee.SqliteDatabase(':memory:')
            database_proxy.initialize(db)
            db.create_tables([A, B])
            A(a_attribute_1 = 9705,
              a_attribute_2 = 0.77,
              ba1 = "this is b")
    
        def test_a(self):
            b = B.select().where(B.b_attribute_1 == 'this is b').get()
            self.assertEqual(b.b_attribute_1, 'this is b')
            self.assertEqual(b.a.a_attribute_1, 9705)
    
    
    if __name__ == '__main__':
        unittest.main()
    

    【讨论】:

      猜你喜欢
      • 2017-07-21
      • 1970-01-01
      • 2020-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多