在将这些数据发送到pgsql之前,我怎样才能手动验证这些数据?

是否有任何库已经通过从pgsql中提取模式信息并对其进行验证来做到这一点?

5 个评论
捕捉INSERT语句中可能出现的异常有什么问题?
@Sebastian 所以基本上我无法控制将信息抛给msg bus然后再抛给db的库,所以在移交数据之前验证数据是非常重要的,抱歉为了简单起见我没有提到这一点。
AKX
你可以使用外面的任何验证库,如 marshmallow pydantic
那么,在调用你的库代码之前,创建一个表foo的影子 create table foo_shadow (like foo including constraints) 并尝试向其中插入(开始-插入-回滚,当然要寻找异常)。
@Stefanov.sm 是的,这是一种方法,但有很多超过300的表......我在想是否有办法从pgsql拉出模式,并根据该模式进行验证。
python
python-3.x
database
postgresql
validation
ThomasBecker
ThomasBecker
发布于 2021-06-02
6 个回答
Glauco
Glauco
发布于 2021-06-18
已采纳
0 人赞同

第一步是从数据库本身检索预期的数据类型,这可以按照@gaurav的建议完成)使用a:

SELECT column_name, data_type FROM information_schema.columns where ...

这给你提供了类型模式,这可以作为 "验证模式 "使用。

simple example - diy

这里有一个简单的例子,用来检查输入的数据是否可以被类型化(它将被postgres以同样的方式铸造,也许)。

from datetime import datetime
schema = {"id": "integer", "enter_time": "TIMESTAMP", "comment": 'text'}
def is_valid(v, validator):
    # dummy validator, we try to apply a constructor
    # returns only True/False, 
    # If False... we don't know why!
    # here you can use a RE for check if input is syntactically correct
        validator(v)
    except:
        return False
    else:
        return True
# type to validator
binding = {'integer':int,
           'TIMESTAMP': datetime.fromtimestamp,
           'text':str}
#validation schemaa
val_schema = {k:binding[v] for k,v in schema.items()}
foo_user = {"id": 123, "enter_time": None, "comment": ''}
for k,v in foo_user.items():
    print (k, ':', is_valid(v, val_schema[k]))
# id : True
# enter_time : False
# comment : True

better approach

对于第二步,有专门的验证库,它们可以进行打字、剪切和模式验证(如2个字段的密码必须相同)以及很多有用的东西。

我曾与很多voluptuous but 许多选择到现在为止,在你的资料库中采用一个库之前,请做好调查。

LongBeard_Boldy
LongBeard_Boldy
发布于 2021-06-18
0 人赞同

该查询返回 "mytable1 "的列名、类型和默认值

 SELECT attname 
      ,pg_catalog.format_type(a.atttypid, a.atttypmod) as Datatype 
      ,coalesce(d.adsrc,'') AS default_value
  FROM pg_catalog.pg_attribute a 
  LEFT JOIN pg_catalog.pg_attrdef d ON (a.attrelid, a.attnum)=(d.adrelid,d.adnum)
 WHERE a.attnum > 0 AND NOT a.attisdropped
   AND a.attrelid = ( SELECT c.oid
                       FROM pg_catalog.pg_class c 
                       LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace 
                      WHERE c.relname = 'mytable1' AND pg_catalog.pg_table_is_visible(c.oid))
    
Karolos K.
Karolos K.
发布于 2021-06-18
0 人赞同

如果你愿意加入ORM,有几种方法可以检索到你的模式。

来自SQLAlchemy的自动映射。 https://docs.sqlalchemy.org/en/14/orm/extensions/automap.html

它将把你的模式映射到类上,然后你就可以使用这种映射来插入你的数据。

还有这个包 https://pypi.org/project/sqlacodegen/ 它在代码库中把表生成为类。

如果你想从DB中直接提取有关列的信息,PostgreSQL的information_schema列表持有这些数据。

SELECT  
  column_name,
  ordinal_position,
  column_default,
  is_generated,
  is_nullable,
  data_type
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'test';

或者对于一个完整的模式

SELECT  
   column_name,
   ordinal_position,
   column_default,
   is_generated,
   is_nullable,
   data_type
FROM INFORMATION_SCHEMA.COLUMNS WHERE  table_schema='test';
    
gaurav
gaurav
发布于 2021-06-18
0 人赞同

如果我没有理解错的话,你想在插入数据库之前,让表的模式与当前的输入相匹配。

cur.execute("SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'foo';")
print(dict(cur.fetchall()))
#{"id": "integer", "enter_time": "TIMESTAMP", "comment": 'text'}
    
Henshal B
Henshal B
发布于 2021-06-18
0 人赞同

为此,你可以使用ORMs。很多人都在使用SQLAlchemy。

Prayson W. Daniel
Prayson W. Daniel
发布于 2021-06-18
0 人赞同

使用 pydantic ,你可以将输入验证为。

from datetime import datetime
from pydantic import BaseModel, validator
class FooModel(BaseModel):
    id: int
    enter_time: datetime
    comment: str
    @validator('id')
    def id_cannot_be_none(cls, v):
        if v is None:
            raise ValueError('id can not be None')
        return v
    @validator('enter_time')
    def enter_time_cannot_be_none(cls, v):
        if v is None:
            raise ValueError('enter_time can not be None')
        return v
# validate inputs