我需要格式化一些电话号码,我想要的格式为'(ddd)ddd-dddd'
。我偷了Python: removing characters except digits from string的代码,并一如既往地投票。它在大多数情况下工作正常,但有些事情我不明白。
我有一个名为CustomerStudent
的Django模型,它有一个cell_phone
和business_phone
字段。我的保存方法:
def save(self, *args, **kwargs):
self.cell_phone = format_phone(self.cell_phone)
self.business_phone = format_phone(self.business_phone)
super(CustomerStudent, self).save(*args, **kwargs)
format_phone
方法位于我的util.py
文件中。
def format_phone(str=None):
if str is None:
return str
all = string.maketrans('', '')
nodigs=all.translate(all, string.digits)
raw_phone = str.translate(all, nodigs)
if len(raw_phone) == 10:
pass
elif len(raw_phone) == 7:
raw_phone = '000' + raw_phone
else:
return None
return '(%s)%s-%s' % (raw_phone[0:3:1], raw_phone[3:6:1], raw_phone[6::1])
当我遇到这个问题时,我正在编写测试来检查这个模型。
使用以下值构建测试模型:
cell_phone = '5555555555'
business_phone = '999-9999'
tests.py
s = CustomerStudent.objects.get(pk=1)
self.assertEqual(s.cell_phone, '(555)555-5555') # Passes
self.assertEqual(s.business_phone, '(000)999-9999') # Passes
s.cell_phone = 'a5-55l7i77(7/7e7p7-)'
s.save()
self.assertEqual(s.cell_phone, '(555)777-7777') # Passes
self.assertEqual(s.business_phone, '(000)999-9999') # Fails
错误消息:
Creating test database for alias 'default'...
.........E............
======================================================================
ERROR: test_customer_student (training.tests.TrainingTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/path/to/app/tests.py", line 281, in test_customer_student
s.save()
File "/path/to/app/models.py", line 149, in save
self.business_phone = format_phone(self.business_phone)
File "path/to/app/util.py", line 16, in format_phone
raw_phone = str.translate(all, nodigs)
TypeError: translate() takes exactly one argument (2 given)
----------------------------------------------------------------------
Ran 22 tests in 0.968s
FAILED (errors=1)
Destroying test database for alias 'default'...
我知道Unicode的行为有所不同,但我确保新电话号码中存在格式正确的电话号码中的所有字符。我决定抓住TypeError
并返回None
。
def format_phone(str=None):
if str is None:
return str
all = string.maketrans('', '')
nodigs=all.translate(all, string.digits)
try:
raw_phone = str.translate(all, nodigs)
except TypeError:
return None
if len(raw_phone) == 10:
pass
elif len(raw_phone) == 7:
raw_phone = '000' + raw_phone
else:
return None
return '(%s)%s-%s' % (raw_phone[0:3:1], raw_phone[3:6:1], raw_phone[6::1])
现在我运行测试时:
Creating test database for alias 'default'...
.........F............
======================================================================
FAIL: test_customer_student (training.tests.TrainingTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/path/to/app/tests.py", line 283, in test_customer_student
self.assertEqual(s.business_phone, '(000)999-9999')
AssertionError: None != '(000)999-9999'
----------------------------------------------------------------------
Ran 22 tests in 0.954s
FAILED (failures=1)
Destroying test database for alias 'default'...
现在提出问题。为什么在数字未更改时会发生这种情况?我认为它与Unicode有关,但新的cell_number
中包含相同的字符,并且正确地运行format_phone
。
我可以通过检查保存方法中的电话号码是否已更改来解决这个问题,但这似乎是可以避免的开销。建议?
答案 0 :(得分:1)
您可以强制使用常规字符串:
def format_phone(phone_str=None):
phone_str = phone_str.encode('ascii', 'ignore')
[...]
如图所示here