Rob*_*uin 3

Expandos 的两个常见用途是部分固定架构和删除旧属性。

当我有一种需要跨实体略有不同的属性时,我经常使用 Expando;换句话说,当我需要“部分”动态模式时。一个用例是一个接受订单的应用程序,其中有些产品是液体(例如水),有些是物理单位(例如 DVD),有些是“其他”产品(例如面粉)。某些字段,如商品代码、价格和数量,始终是必需的。但是,如果还需要计算数量的详细信息怎么办?

通常,固定模式解决方案是为我们可能使用的所有变量添加一个属性:重量、尺寸、库存的前后重量等等。太糟糕了。对于每个实体来说,大多数其他字段都是不需要的。

class Order(db.Model):
    # These fields are always needed.
    item_code = db.StringProperty()
    unit_of_measure = db.StringProperty()
    unit_price = db.FloatProperty()
    quantity = db.FloatProperty()

    # These fields are used depending on the unit of measure.
    weight = db.FloatProperty()
    volume = db.FloatProperty()
    stock_start_weight = db.FloatProperty()
    stock_end_weight = db.FloatProperty()
Run Code Online (Sandbox Code Playgroud)

有了 Expando,我们可以做得更好。我们可以使用 来unit_of_measure告诉我们如何计算数量。计算数量的函数可以设置动态字段,读取该方法信息的函数知道要查找什么。而且,该实体没有一堆不需要的属性。

class Order(db.Expando):
    # Every instance has these fields.
    item_code = db.StringProperty()
    unit_of_measure = db.StringProperty()
    unit_price = db.FloatProperty()
    quantity = db.FloatProperty()


def compute_gallons(entity, kilograms, kg_per_gallon):
    # Set the fixed fields.
    entity.unit_of_measure = 'GAL'
    entity.quantity = kilograms / kg_per_gallon

    # Set the gallon specific fields:
    entity.weight = kilograms
    entity.density = kg_per_gallon
Run Code Online (Sandbox Code Playgroud)

您可以通过使用文本或 blob 属性并将“其他”值的字典序列化到它来获得类似的结果。Expando 基本上会为您“自动化”这一过程。