{"id":1887,"date":"2009-11-25T11:56:35","date_gmt":"2009-11-25T02:56:35","guid":{"rendered":"http:\/\/fukata.org\/?p=1887"},"modified":"2017-08-11T22:59:08","modified_gmt":"2017-08-11T22:59:08","slug":"gae-p-validationmanager","status":"publish","type":"post","link":"https:\/\/blog.fukata.org\/archives\/1887\/","title":{"rendered":"[GAE\/P]\u72ec\u81ea\u306eValidationManager\u3092\u4f5c\u3063\u3066\u307f\u307e\u3057\u305f"},"content":{"rendered":"

GAE\u3067\u30a2\u30d7\u30ea\u3092\u4f5c\u6210\u3057\u3066\u3044\u3066\u3001\u5165\u529b\u5024\u3078\u306e\u691c\u8a3c\u6a5f\u69cb\u304c\u8ca7\u5f31\u3060\u3068\u601d\u3063\u305f\u306e\u3067\u3001\u4f5c\u308a\u307e\u3057\u305f\u3002\u4eca\u56de\u4f5c\u6210\u3057\u305f\u306e\u306f\u3001\u691c\u8a3c\u60c5\u5831\u3092yaml\u306b\u8a18\u8ff0\u3057\u3001\u305d\u306e\u691c\u8a3c\u60c5\u5831\u306b\u6cbf\u3063\u3066\u30e2\u30c7\u30eb\u306e\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u8d70\u67fb\u3057\u3066\u3044\u304f\u3068\u3044\u3046\u7269\u3067\u3059\u3002<\/p>\n

\u691c\u8a3c\u60c5\u5831yaml\u306e\u8a18\u8ff0\u65b9\u6cd5\u3001\u4f7f\u3044\u65b9\u3068\u3082\u306bSymfony\u306eValidationManager\u306b\u9177\u4f3c\u3057\u3066\u3044\u308b\u3068\u601d\u3044\u307e\u3059\u3002\u306a\u306e\u3067\u3001Symfony\u3092\u4f7f\u3063\u305f\u3053\u3068\u304c\u3042\u308b\u4eba\u3067\u3042\u308c\u3070\u3001\u306a\u3093\u3068\u306a\u304f\u308f\u304b\u308a\u3084\u3059\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002\u3068\u8a00\u3063\u3066\u3082\u3001Symfony\u306eValidationManager\u307b\u3069\u307e\u3060\u7d30\u90e8\u307e\u3067\u30a8\u30e9\u30fc\u30c1\u30a7\u30c3\u30af\u306a\u3069\u3092\u3057\u3066\u3044\u306a\u3044\u306e\u3067\u3001\u691c\u8a3c\u60c5\u5831yaml\u306e\u8a18\u8ff0\u306b\u3088\u3063\u3066\u306f\u3001\u4e88\u671f\u3057\u306a\u3044\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3059\u308b\u3068\u601d\u3044\u307e\u3059\u3002\u3067\u3059\u306e\u3067\u3001\u3053\u306e\u8fba\u306f\u3001\u3082\u3046\u5c11\u3057\u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u3092\u3057\u306a\u3044\u3068\u3044\u3051\u306a\u3044\u304b\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n

Python\u306b\u3088\u308b\u30ea\u30d5\u30ec\u30af\u30b7\u30e7\u30f3\u90e8\u5206\u3060\u3063\u305f\u308adb.Model\u306e\u6271\u3044\u65b9\u304c\u3082\u3057\u9593\u9055\u3063\u3066\u3044\u305f\u3089\u662f\u975e\u6559\u3048\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n

\u4eca\u56de\u3001\u95a2\u4fc2\u3059\u308b\u30bd\u30fc\u30b9\u306f\u4e0b\u8a18\u306b\u8f09\u305b\u3066\u304a\u304d\u307e\u3059\u3002<\/p>\n

\u25a0\u691c\u8a3c\u60c5\u5831yaml<\/p>\n

\r\nvalidate:\r\n  name:\r\n    - validator: RequiredValidator\r\n<\/pre>\n

\u25a0ValidationManager<\/p>\n

\r\nclass ValidationManager(object):\r\n    VALIDATOR_PACKAGES = [\r\n                          'org.fukata.mapshare.system.utils.validation.common.',\r\n                          'org.fukata.mapshare.system.utils.validation.extention.',\r\n                          ]\r\n    \r\n    valid = None\r\n    errors = None\r\n    \r\n    def __init__(self,validYaml):\r\n        self.valid = YamlUtils.load(validYaml)\r\n        \r\n    def validate(self,model):\r\n        # initialize\r\n        self.errors = Errors()\r\n        \r\n        for item in self.valid[config.VALIDATE_KEY]:\r\n            for validInfo in self.valid[config.VALIDATE_KEY][item]:\r\n                validator = self._getValidatorInstance(validInfo)\r\n                # check exists attribute\r\n                props = model.properties()\r\n                prop = None\r\n                if props.has_key(item):\r\n                    prop = props[item]\r\n                else:\r\n                    # don't have a key.\r\n                    raise BadKeyError(\"Key %s is don't have property.\" % item)\r\n                \r\n                value = getattr(model, prop._attr_name(), None)\r\n                try:\r\n                    validator.validate(value, prop, model)\r\n                except ValidationError, e:\r\n                    self.errors.append(prop, e.__str__())\r\n                \r\n        return not bool(self.errors)\r\n    \r\n    def _getValidatorInstance(self, validInfo):\r\n\r\n        clazz = ReflectionUtils.getClazz(validInfo['validator'], self.VALIDATOR_PACKAGES);\r\n        options = validInfo['options'] if validInfo.has_key('options') else {} \r\n        return clazz(options)\r\n<\/pre>\n

\u25a0ValidationError<\/p>\n

\r\nclass ValidationError(Exception):\r\n    def __init__(self, value):\r\n        self.value = value\r\n        \r\n    def __str__(self):\r\n        return self.value\r\n<\/pre>\n

\u25a0BaseValidator<\/p>\n

\r\nclass BaseValidator(object):\r\n    options = None\r\n\r\n    def __init__(self, options=None):\r\n        self.options = options\r\n        \r\n    def validate(self,value,prop,model):\r\n        return False\r\n<\/pre>\n

\u25a0RequiredValidator<\/p>\n

\r\nclass RequiredValidator(BaseValidator):\r\n    def validate(self,value,prop,model):\r\n        if value is None:\r\n            raise ValidationError('Property %s is required' % prop.name)\r\n\r\n        if StringUtils.isNone(value):\r\n            raise ValidationError('Property %s is required' % prop.name)\r\n        \r\n        return True\r\n<\/pre>\n

\u25a0BaseModel<\/p>\n

\r\n# skip default validation of db.Property\r\nsetattr(db.Property, '__set__', \r\n        lambda self, model_instance, value: \r\n            setattr(model_instance, self._attr_name(), value))\r\n\r\nclass BaseModel(db.Model):\r\n    errors = None\r\n\r\n    def __init__(self, *args, **kwds):\r\n        super(BaseModel, self).__init__(*args, **kwds)\r\n        self.errors = Errors()\r\n\r\n    def validate(self,valid_yaml=None):\r\n        if valid_yaml is None:\r\n            for prop in self.properties().values():\r\n                value = getattr(self, prop._attr_name(), None)\r\n                try:\r\n                    value = prop.validate(value)\r\n                    setattr(self, prop._attr_name(), value)\r\n                except db.BadValueError, e:\r\n                    self.errors.append(prop, e.message)\r\n            return not bool(self.errors)\r\n        else:\r\n            manager = ValidationManager(valid_yaml)\r\n            manager.validate(self)\r\n            self.errors = manager.errors\r\n            return not bool(self.errors)\r\n<\/pre>\n

\u25a0Errors<\/p>\n

\r\nclass Errors(list):\r\n    '''container of validation errors\r\n    '''\r\n    def __init__(self):\r\n        self.map = dict()\r\n\r\n    def append(self, prop, msg=None, error=True):\r\n        if error:\r\n            if isinstance(prop, db.Property):\r\n                super(Errors, self).append(Error(prop, msg))\r\n                self.map[prop.name] = len(self) - 1\r\n            elif isinstance(prop, (str, unicode)):\r\n                super(Errors, self).append(Error(prop, msg))\r\n                self.map[prop] = len(self) - 1\r\n            else:\r\n                super(Errors, self).append(Error(None, prop))\r\n\r\n    def clear(self):\r\n        del self[:]\r\n    \r\n    def get(self, index, default=None):\r\n        return self[index] if index in self else default\r\n\r\n    def tostr(self, sep=u\"\\n\", **ops):\r\n        msgs=list()\r\n        for error in self:\r\n            msgs.append(error.tostr(**ops))\r\n        return sep.join(msgs)\r\n\r\n    def __str__(self):\r\n        return self.tostr()\r\n\r\n    def __contains__(self, name):\r\n        return name in self.map\r\n    \r\n    def __getitem__(self, index):\r\n        if isinstance(index, (str, unicode)):\r\n            if index not in self.map:\r\n                raise IndexError(u\"'%s' property has not error.\" % index)\r\n            index = self.map[index]\r\n        return super(Errors, self).__getitem__(index)\r\n<\/pre>\n

\u25a0Error<\/p>\n

\r\nclass Error(object):\r\n    '''container of validation error\r\n    '''\r\n    \r\n    def __init__(self, prop, msg=None):\r\n        self.prop = prop\r\n        self.msg = msg\r\n\r\n    def __str__(self):\r\n        return self.tostr()\r\n\r\n    def tostr(self, format=u\"%(msg)s\"):\r\n        if isinstance(self.prop, db.Property) and format:\r\n            name = self.prop.verbose_name or self.prop.name\r\n            msg = re.sub(' '+name+' ', ' %(name)s ', self.msg)\r\n            format = format % {\r\n                            'msg': msg,\r\n                        }\r\n            return _(format) % {\r\n                             'name': _(self.prop.verbose_name) or _(self.prop.name),\r\n                            }\r\n        else:\r\n            return _(self.msg)\r\n<\/pre>\n

\u25a0ReflectionUtils<\/p>\n

\r\nclass ReflectionUtils(object):\r\n    BIG_PATTERN = re.compile('[A-Z]')\r\n    \r\n    @classmethod\r\n    def getClazz(cls,className,basePackageList=[]):\r\n        packageName = cls.generatePackageName(className)\r\n        \r\n        clazz = None\r\n        if len(basePackageList)>0:\r\n            for basePackage in basePackageList:\r\n                packageName = basePackage+packageName\r\n                try:\r\n                    module = __import__(packageName, globals(), locals(), [className])\r\n                    clazz = getattr(module, className)\r\n                except ImportError, e:\r\n                    continue\r\n                except AttributeError, e:\r\n                    continue\r\n        else:\r\n            try:\r\n                module = __import__(packageName, globals(), locals(), [className])\r\n                clazz = getattr(module, className)\r\n            except ImportError, e:\r\n                pass\r\n            except AttributeError, e:\r\n                pass\r\n        \r\n        if clazz is None:\r\n            raise AttributeError('%s class is not exists.' % className)\r\n        \r\n        return clazz\r\n        \r\n    \r\n    @classmethod\r\n    def newInstance(cls,className,basePackageList=[]):\r\n        try:\r\n            clazz = cls.getClazz(className, basePackageList)\r\n            instance = clazz()\r\n        except ImportError, e:\r\n            pass\r\n        except AttributeError, e:\r\n            pass\r\n        \r\n        if instance is None:\r\n            raise AttributeError('%s is not exists.' % className)\r\n        \r\n        return instance\r\n    \r\n    @classmethod\r\n    def generatePackageName(cls,className):\r\n        split = cls.BIG_PATTERN.split(className)\r\n        findall = cls.BIG_PATTERN.findall(className)\r\n        \r\n        str_list = []\r\n        white=0\r\n        for i in range(len(split)):\r\n            if split[i]:\r\n                head = findall[i-white].lower()\r\n                str = head+split[i]\r\n                str_list.append(str)\r\n            else:\r\n                white = white+1\r\n                \r\n        return '_'.join(str_list)\r\n<\/pre>\n

\u25a0YamlUtils<\/p>\n

\r\nclass YamlUtils(object):\r\n    \r\n    @classmethod\r\n    def load(cls,path):\r\n        return yaml.load(cls._get_stream(path))\r\n    \r\n    @classmethod\r\n    def load_all(cls,path):\r\n        return yaml.load_all(cls._get_stream(path))\r\n    \r\n    @classmethod\r\n    def _get_stream(cls,path):\r\n        fp = open(path, 'r')\r\n        stream = fp.read()\r\n        fp.close()\r\n        return stream\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"

GAE\u3067\u30a2\u30d7\u30ea\u3092\u4f5c\u6210\u3057\u3066\u3044\u3066\u3001\u5165\u529b\u5024\u3078\u306e\u691c\u8a3c\u6a5f\u69cb\u304c\u8ca7\u5f31\u3060\u3068\u601d\u3063\u305f\u306e\u3067\u3001\u4f5c\u308a\u307e\u3057\u305f\u3002\u4eca\u56de\u4f5c\u6210\u3057\u305f\u306e\u306f\u3001\u691c\u8a3c\u60c5\u5831\u3092yaml\u306b\u8a18\u8ff0\u3057\u3001\u305d\u306e\u691c\u8a3c\u60c5\u5831\u306b\u6cbf\u3063\u3066\u30e2\u30c7\u30eb\u306e\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u8d70\u67fb\u3057\u3066\u3044\u304f\u3068\u3044\u3046\u7269\u3067\u3059\u3002 \u691c\u8a3c … \u7d9a\u304d\u3092\u8aad\u3080<\/a><\/p>\n","protected":false},"author":2,"featured_media":9223372036854775807,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1980],"tags":[403,404,410],"_links":{"self":[{"href":"https:\/\/blog.fukata.org\/wp-json\/wp\/v2\/posts\/1887"}],"collection":[{"href":"https:\/\/blog.fukata.org\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.fukata.org\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.fukata.org\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.fukata.org\/wp-json\/wp\/v2\/comments?post=1887"}],"version-history":[{"count":0,"href":"https:\/\/blog.fukata.org\/wp-json\/wp\/v2\/posts\/1887\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.fukata.org\/wp-json\/wp\/v2\/media\/9223372036854775807"}],"wp:attachment":[{"href":"https:\/\/blog.fukata.org\/wp-json\/wp\/v2\/media?parent=1887"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.fukata.org\/wp-json\/wp\/v2\/categories?post=1887"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.fukata.org\/wp-json\/wp\/v2\/tags?post=1887"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}