如何防止在python中插入与模型不同的记录

时间:2016-05-20 14:38:45

标签: python oop python-3.x

我有一个数据模型,它具有一些原始和数组类型属性,如下所示:

class WordCollection:
    """First model"""
    def __init__(self, **properties):
        self.name = ""
        self.status = CommonStatus.active
        self.expire_time = time.time() + 1000 * 60 * 24  # after 1 day
        self.created_date = time.time()
        self.words = []
        self.__dict__.update(properties)

这是一些黑客攻击。例如,当我使用不属于类的属性构造类时,它很容易被黑客攻击。

collection = WordCollection(**{..., "hack_property":"large text or irrelative data"})

所以我在课堂初始化方法上玩了:

class WordCollection:
        """Second model"""
        def __init__(self, **properties):
            self.name = properties["name"] if "name" in properties else ""
            self.status = properties["active"] if "active" in properties else CommonStatus.active
            self.expire_time = properties["expire_time"] if "expire_time" in properties else time.time() + 1000 * 60 * 24  # after 1 day
            self.created_date = properties["created_date"] if "created_date" in properties else time.time()
            self.words = properties["words"] if "words" in properties else []

但是上面的代码并没有完全解决问题:

collection = WordCollection(**{..., "name":{"hack_property":"large text or irrelative data"}})

这是最后一次重建的代码:

    class WordCollection:
        """Third Model"""
        def __init__(self, **properties):
            self.name = properties["name"] if "name" in properties and isinstance(properties["name"], str) else ""
            self.status = properties["active"] if "active" in properties \
                                                  and isinstance(properties["status"], int) else CommonStatus.active
            ....

以上版本解决了我的问题,但它带来了条件复杂性,我相信这将是比上述更好的解决方案。

1 个答案:

答案 0 :(得分:0)

更标准的配方:

valid_properties =  {'prop1', 'prop2', 'prop3'}
class WordCollection(object):
    def __init__(self, name="", status=None; **properties):
        # This one is explicit, with a default that is specified in the call signature
        # Defaults in the call signature are resolved when the class is imported
        self.name = name
        # This one is more dynamic - CommonStatus.active could change
        # after the user imports the class, so we don't want it fixed.
        # Instead, use a sentinel.
        # I usually use None. If None is a valid value, best bet
        # is to do something like this:
        # sentinel = object()
        # then use that instead of None.
        self.status = CommonStatus.active if status is None else status
        # This one we just assign - 
        self.words = []
        # You don't _have_ to include a **kwargs if you don't want to.
        # If you don't want _any_ surprise properties, just leave
        # **properties out of the __init__, and only ones you explicit
        # declare will be allowed.
        # Explicit is better - they show up in tab completion/help
        # But if you want to filter out input to a set of valid props...
        filtered_props = {k:v for k,v in properties.items() if k in valid_properties}
        self.__dict__.update(filtered_props)