0
我想清理我想要添加到一個數據庫SQLAlchemy的,以確保它是正確的類型的一些舉步維艱的數據。所以我正在嘗試將字符串截斷爲正確的列長度。使用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
很容易,當你知道如何!