2017-01-30 3 views
0

SQLAlchemy 데이터베이스에 추가하려는 일부 ropey 데이터를 정리하려고합니다. 올바른 유형인지 확인합니다. 그래서 저는 예를 들어 문자열을 올바른 열 길이로 자릅니다.setattr 및 __init__을 사용하여 SQLAlchemy 데이터 정리

나는 이것을 시행하기 위해 getattr()setattr()을 사용하는 생성자를 생성 해 보았습니다. 하지만 몇 가지 이유로 문자열 등 잘린되지 않습니다 .. 어떤 제안?

class Property(Base): 
    """ 
    Property details as imported from various Council sources 
    """ 
    MAXPROPREFLEN = 20 
    MAXADDRESSLEN = 100 
    MAXDESCRIPLEN = 120 
    MAXPOSTCODELEN = 10 

    __tablename__ = 'properties' 
    id    = Column(Integer, primary_key=True) 
    PropertyRef = Column(String(MAXPROPREFLEN)) # Council reference, diffrerent from UPRN 
    AccountHolder = Column(String(MAXDESCRIPLEN)) 
    Address1  = Column(String(MAXADDRESSLEN)) 
    Address2  = Column(String(MAXADDRESSLEN)) 
    Address3  = Column(String(MAXADDRESSLEN)) 
    Address4  = Column(String(MAXADDRESSLEN)) 
    PostCode  = Column(String(MAXPOSTCODELEN), index=True) 
    UPRN   = Column(BigInteger) 
    Description = Column(String(MAXDESCRIPLEN)) 
    RV    = Column(Numeric(10, 0)) 
    Empty   = Column(Boolean) 
    LiableFrom  = Column(Date) 
    EmptySince  = Column(Date) 
    MEBID   = Column(Integer) # Key in MEB table if applicable 
    Authority  = Column(Integer) # Key in authorities table 

    def __init__(self, **kwargs): 
     """ 
     Ordinarily we wouldn't require a constructor, but the data from the 
     various LAs is of such poor quality and the Psycopg2 connector 
     so strict about types that we have to clean it up. So we need to 
     truncate overly long strings etc. 
     """ 
     for key, value in kwargs.items(): 
      if key == 'PropertyRef': 
       setattr(self, key, value[:Property.MAXPROPREFLEN] if value else None) 
      elif key == 'PostCode': 
       setattr(self, key, value[:Property.MAXPOSTCODELEN] if value else None) 
      elif key in ['AccountHolder', 'Description']: 
       if type(value) is str: 
        setattr(self, key, value[:Property.MAXDESCRIPLEN]) 
       else: 
        setattr(self, key, None) 
      elif key in ['Address1', 'Address2', 'Address3', 'Address4']: 
       setattr(self, key, value[:Property.MAXADDRESSLEN] if value else None) 
      elif key in ['LiableFrom','EmptySince']: 
       if type(value) == datetime.datetime: 
        setattr(self, key, value.date()) 
       elif type(value) == datetime.date: 
        setattr(self, key, value) 
       else: 
        setattr(self, key, None) 
      if key == 'UPRN': 
       if type(value) is str: 
        try: 
         setattr(self, key, int(value)) 
        except ValueError: 
         setattr(self, key, None) 
       elif type(value) is int: 
        setattr(self, key, value) 
       else: 
        setattr(self, key, None) 
      else: 
       setattr(self, key, value) 

UPDATE는

표트르 Dawidiuk 덕분에, 고정. 지금은

class Property(Base): 
    """ 
    Property details as imported from various Council sources 
    """ 
    MAXPROPREFLEN = 20 
    MAXADDRESSLEN = 80 
    MAXDESCRIPLEN = 80 
    MAXPOSTCODELEN = 10 

    __tablename__ = 'properties' 
    id    = Column(Integer, primary_key=True) 
    PropertyRef = Column(String(MAXPROPREFLEN)) # Council reference, diffrerent from UPRN 
    AccountHolder = Column(String(MAXDESCRIPLEN)) 
    Address1  = Column(String(MAXADDRESSLEN)) 
    Address2  = Column(String(MAXADDRESSLEN)) 
    Address3  = Column(String(MAXADDRESSLEN)) 
    Address4  = Column(String(MAXADDRESSLEN)) 
    PostCode  = Column(String(MAXPOSTCODELEN), index=True) 
    UPRN   = Column(BigInteger) 
    Description = Column(String(MAXDESCRIPLEN)) 
    RV    = Column(Numeric(10, 0)) 
    Empty   = Column(Boolean) 
    LiableFrom  = Column(Date) 
    EmptySince  = Column(Date) 
    MEBID   = Column(Integer) # Key in MEB table if applicable 
    Authority  = Column(Integer) # Key in authorities table 


    @validates('PropertyRef', 'AccountHolder', 'Description', 
       'Address1', 'Address2', 'Address3', 'Address4', 'PostCode') 
    def ValidateString(self, key, value): 
     maxlengths = {'PropertyRef': Property.MAXPROPREFLEN, 
         'AccountHolder': Property.MAXDESCRIPLEN, 
         'Description': Property.MAXDESCRIPLEN, 
         'Address1':  Property.MAXADDRESSLEN, 
         'Address2':  Property.MAXADDRESSLEN, 
         'Address3':  Property.MAXADDRESSLEN, 
         'Address4':  Property.MAXADDRESSLEN, 
         'PostCode':  Property.MAXPOSTCODELEN 
         } 

     if type(value) is str: 
      value = value.strip().upper() 
      if len(value) > maxlengths[key]: 
       logger.debug("Timmming {} <{}> to <{}> ({} to {} chars)".format(
          key, value, value[:maxlengths[key]], 
          len(value), maxlengths[key])) 
      return value[:maxlengths[key]] 
     else: 
      return None 

    @validates('LiableFrom', 'EmptySince') 
    def ValidateDate(self, key, value): 
     if type(value) == datetime.datetime: 
      return value.date() 
     elif type(value) == datetime.date: 
      return value 
     else: 
      return None 

    @validates('UPRN') 
    def ValidateInteger(self, key, value): 
     try: 
      return int(value) 
     except: 
      return None 

    @validates('RV') 
    def ValidateFloat(self, key, value): 
     try: 
      return float(value) 
     except: 
      return None 

어떻게 알 수 있습니까?

답변

1

이렇게하지 마십시오. 이 개념은 validatesdecorator입니다.

속성 검사기는 속성의 값을 돌연변이 과정을 중단, 예외를 발생하거나 다른 무언가로 지정된 값을 변경할 수있다.

수정 된 필터링 된 깨끗한 데이터 만 유효성 검사기에 반환하십시오.

도 참조하십시오. Changing Attribute Behavior 문서 섹션.

관련 문제