【问题标题】:What is the best practice to populate a StructuredProperty through the ndb.Model constructor?通过 ndb.Model 构造函数填充 StructuredProperty 的最佳实践是什么?
【发布时间】:2018-03-30 10:05:27
【问题描述】:

我查看了ndb GitHub 示例代码,但找不到任何示例 它显示了如何使用包含 StructuredProperty 的构造函数创建 ndb 实体。

这里是 GitHub example

如果我想用电话号码列表初始化Contact 实体,而这个电话号码列表不是PhoneNumber 对象列表,该怎么办。相反,它是一个 Python 字典列表。

所以,给定以下Model 类:

class PhoneNumber(ndb.Model):
    """A model representing a phone number."""
    phone_type = ndb.StringProperty(
        choices=('home', 'work', 'fax', 'mobile', 'other'))
    number = ndb.StringProperty()


class Contact(ndb.Model):
    """A Contact model that uses StructuredProperty for phone numbers."""
    # Basic info.
    name = ndb.StringProperty()
    birth_day = ndb.DateProperty()

    # Address info.
    address = ndb.StringProperty()

    phone_numbers = ndb.StructuredProperty(PhoneNumber, repeated=True)

我想使用以下 Python 字典创建 Contact

phone_number_dicts = [{"phone_type" : "home", number = 122}, {"phone_type" : "work", number = 123}]

contact = Contact(name = "some name", birthday = "some day", phone_numbers = phone_number_dicts)
  1. 我是否需要将 dict 显式转换为 ndb 实体?
  2. 我可以覆盖 ndb 构造函数,它将字典转换为 ndb 实体并赋值吗?
  3. 还有其他更好的方法吗?

【问题讨论】:

    标签: google-app-engine app-engine-ndb google-app-engine-python


    【解决方案1】:

    代替

    phone_number_dicts = [{"phone_type" : "home", number = 122}, {"phone_type" : "work", number = 123}]
    contact = Contact(name = "some name", birthday = "some day", phone_numbers = phone_number_dicts)
    

    你需要有这样的东西:

    phone_numbers = [
        PhoneNumber(phone_type="home", number=123),
        PhoneNumber(phone_type="work", number=123)
    ]
    contact = Contact(name="some name", birthday="some day", phone_numbers=phone_numbers)
    

    即制作PhoneNumber 实体的列表,而不是dicts 的列表。

    您也可以将 dict 传递给 ndb 实体,以便使用 populate method 填充它,即如果您已经拥有该行

    phone_number_dicts = [{"phone_type" : "home", number = 122}, {"phone_type" : "work", number = 123}]
    

    你无法控制,你可以这样做

    phone_numbers = [PhoneNumber().populate(**entity) for entity in phone_number_dicts]
    

    从现有的dicts 列表创建PhoneNumbers 列表,然后再次将其传递给Contact 构造函数。

    【讨论】:

    • 感谢您的回复。所以这意味着,在传递给构造函数之前,我必须将 dict 转换为 ndb 实体。没有其他方法可以让 ndb 自动将 dict 映射到 ndb 属性?
    • 差不多...如果你想存储dictlistdicts - 查看PickleProperty or JsonProperty
    【解决方案2】:

    只需重写PhoneNumber 构造函数,这样您就可以通过Contact 构造函数将字典作为kwargs 传递给它的构造函数。

    class PhoneNumber(ndb.Model):
        phone_type = ndb.StringProperty(
            choices=('home', 'work', 'fax', 'mobile', 'other'))
        number = ndb.StringProperty()
    
        def __init__(self, *args, **kwargs):
            super(PhoneNumber, self).__init__(*args, **kwargs)
            self.__dict__.update(kwargs)
    
    
    class Contact(ndb.Model):
        name = ndb.StringProperty()
        birth_day = ndb.DateProperty()
        address = ndb.StringProperty()
        phone_numbers = ndb.StructuredProperty(PhoneNumber, repeated=True)
        company_title = ndb.StringProperty()
        company_name = ndb.StringProperty()
        company_description = ndb.TextProperty()
        company_address = ndb.StringProperty()
    
        def __init__(self, *args, **kwargs):
            super(Contact, self).__init__(*args, **kwargs)
            if kwargs:
                self.phone_numbers = []
                for kwarg in kwargs.pop('phone_numbers'):
                    if isinstance(kwarg, PhoneNumber):
                        self.phone_numbers.append(kwarg)
                    else:
                        p = PhoneNumber(**kwarg)
                        self.phone_numbers.append(p)
    

    通过这种方式,您可以将PhoneNumber 实体的字典表示传递给Contact 构造函数,或者将PhoneNumber 属性的字典表示传递给PhoneNumber 构造函数。

    这是我通过dev_appserver.py交互式控制台尝试的几个测试用例:

    from google.appengine.ext import ndb
    
    from models import Contact, PhoneNumber
    
    kwargs = {
        'phone_numbers': [{
            'phone_type': 'home',
            'number': '123',
        }, {
            'phone_type': 'work',
            'number': '456',
        }, {
            'phone_type': 'fax',
            'number': '789',
        }]
    }
    
    c = Contact(**kwargs)
    print 'Test Case 1:'
    print c
    print
    
    kwargs = {
        'phone_numbers': [
            PhoneNumber(**{'phone_type': 'home','number': '123'}),
            PhoneNumber(**{'phone_type': 'work','number': '456'}),
            PhoneNumber(**{'phone_type': 'fax', 'number': '789'})
        ]
    }
    
    c = Contact(**kwargs)
    print 'Test Case 2:'
    print c
    print
    
    c = Contact(
        phone_numbers=[
            PhoneNumber(phone_type='home', number='123'),
            PhoneNumber(phone_type='work', number='456'),
            PhoneNumber(phone_type='fax', number='789')
        ]
    )
    print 'Test Case 3:'
    print c
    print
    

    输出

    Test Case 1:
    Contact(phone_numbers=[PhoneNumber(number='123', phone_type='home'), 
    PhoneNumber(number='456', phone_type='work'), 
    PhoneNumber(number='789', phone_type='fax')])
    
    Test Case 2:
    Contact(phone_numbers=[PhoneNumber(number='123', phone_type='home'), 
    PhoneNumber(number='456', phone_type='work'), 
    PhoneNumber(number='789', phone_type='fax')])
    
    Test Case 3:
    Contact(phone_numbers=[PhoneNumber(number='123', phone_type='home'), 
    PhoneNumber(number='456', phone_type='work'), 
    PhoneNumber(number='789', phone_type='fax')])
    

    正如预期的那样,每种情况都会引发相同的 Contact 对象。

    【讨论】:

      猜你喜欢
      • 2022-11-04
      • 1970-01-01
      • 2020-01-11
      • 1970-01-01
      • 2017-01-09
      • 1970-01-01
      • 2011-04-17
      • 2017-09-13
      • 1970-01-01
      相关资源
      最近更新 更多