这里的第一个新手项目-在此模型中,我试图创建一个字段,该字段将两个人的姓氏和名字结合在一起,这取决于姓氏是否相同。如果姓氏相同,我希望它显示为“ first_name1&first_name2 last_name1”。它的工作原理是,当last_name1为空时(在许多情况下会如此),它显示类似“ John&Jane None”的内容。我必须将last_name1指定为字符串,否则会出现错误:必须为str,而不是NoneType。如何正确执行此操作?另外,我在模型中怎么称这种类型的功能……是经理吗?我不确定如何为这篇文章加上标题。
class Contact(models.Model):
first_name1 = models.CharField(max_length=100, verbose_name='First Name', null=True)
last_name1 = models.CharField(max_length=100, verbose_name='Last Name', null=True, blank=True)
first_name2 = models.CharField(max_length=100, verbose_name='First Name (Second Person)', null=True, blank=True)
last_name2 = models.CharField(max_length=100, verbose_name='Last Name (Second Person)', null=True, blank=True)
def get_full_name(self):
combined_name = ''
if self.last_name1 == self.last_name2:
combined_name = self.first_name1 + ' & ' + self.first_name2 + ' ' + str(self.last_name1)
return '%s' % (combined_name)
full_name = property(get_full_name)
答案 0 :(得分:1)
您可以在进行比较检查之前检查那些值是否为“ Truth-y”。但是,您需要确定如何处理其他情况。
find "$1" -type f '(' -name "*.html" -o -name "*.htm" ')' \
-exec ./stripHtml {} {}_nobody \;
答案 1 :(得分:1)
为什么收到错误消息last_name1必须是String而不是NoneType的原因是由于您在所述字段的字段声明中将null设置为True。
那么这样做有什么问题呢?当为CharField或TextField之类的字段定义null = True时,您最终将具有 None 。 Django惯例是使用 EMPTY STRING 。
这里有一个link,它讨论了如何在字段声明中使用空白或空。
答案 2 :(得分:0)
您定义名称的方式,所有名称都可以为None
,如果将其更改为空字符串,您将遇到类似的问题。为了说明,让我们先编写一个单元测试(如果需要,用空字符串替换None):
def test_contact_full_name():
# correct.
assert Contact('Jane', None, 'John', None).full_name == "Jane & John"
assert Contact('Bart', 'Simpson', 'Lisa', 'Simpson').full_name == "Bart & Lisa Simpson"
assert Contact('Bart', 'Simpson', 'Frodo', 'Baggins').full_name == "Bart Simpson & Frodo Baggins"
assert Contact('Bart', None, None, None).full_name == "Bart"
assert Contact('Bart', 'Simpson', None, None).full_name == "Bart Simpson"
assert Contact(None, 'Simpson', None, None).full_name == "Simpson"
assert Contact(None, None, None, None).full_name == ""
# correct?
assert Contact('Bart', 'Simpson', 'Lisa', None).full_name == "Bart Simpson & Lisa"
# correct??
assert Contact('Bart', None, 'Lisa', 'Simpson').full_name == "Bart & Lisa Simpson"
这只是将问题分成小块的问题,我将所有内容放入常规类中只是为了使其易于测试。首先介绍一些辅助方法:
class Contact(object):
def __init__(self, a, b, c, d):
self.first_name1 = a
self.last_name1 = b
self.first_name2 = c
self.last_name2 = d
def combined_last_name(self, a, b):
"Return ``a`` if ``a`` and ``b`` are equal, otherwise returns None."
return a if a and b and a == b else None
def normalize_name(self, n):
"Returns the name or the empty string if ``n`` is None."
return n if n else ""
def get_name(self, f, l):
"""Returns a string containing firstname lastname and omits any of them
if they're None.
"""
if f and l:
return "%s %s" % (f, l)
if f:
return f
elif l:
return l
return ""
def has_second_name(self):
"Returns true if there is a second name."
return self.first_name2 or self.last_name2
然后我们可以定义full_name
属性:
@property
def full_name(self):
"""Returns a string that combines first and last names of two people
depending if the last names are the same or not. If the last name
is the same, it displays as::
first_name1 & first_name2 last_name1
"""
cln = self.combined_last_name(self.last_name1, self.last_name2)
if cln: # have a common last name..
return "%s & %s %s" % (
self.first_name1,
self.first_name2,
cln
)
elif self.has_second_name():
return "%s & %s" % (
self.get_name(self.first_name1, self.last_name1),
self.get_name(self.first_name2, self.last_name2)
)
else:
return self.get_name(self.first_name1, self.last_name1)
如果我们将所有内容都放入名为fullname.py
的文件中,则可以使用pytest
工具(pip install pytest
)来运行测试:
c:\srv\tmp> pytest --verbose fullname.py
============================= test session starts =============================
platform win32 -- Python 2.7.16, pytest-3.3.1, py-1.5.2, pluggy-0.6.0 -- c:\srv\venv\finautfaktura\scripts\python.exe
cachedir: .cache
rootdir: c:\srv\tmp, inifile:
plugins: xdist-1.20.1, forked-0.2, django-3.1.2, cov-2.5.1
collected 1 item
fullname.py::test_contact_full_name PASSED [100%]
========================== 1 passed in 0.20 seconds ===========================
一切都很好...是吗?
我们再写一个测试:
def test_only_second_name():
assert Contact(None, None, None, "Simpson").full_name == "Simpson"
assert Contact(None, None, "Lisa", "Simpson").full_name == "Lisa Simpson"
assert Contact(None, None, "Lisa", None).full_name == "Lisa"
再次运行pytest会显示(第一个)错误:
c:\srv\tmp> pytest --verbose fullname.py
============================= test session starts =============================
platform win32 -- Python 2.7.16, pytest-3.3.1, py-1.5.2, pluggy-0.6.0 -- c:\srv\venv\finautfaktura\scripts\python.exe
cachedir: .cache
rootdir: c:\srv\tmp, inifile:
plugins: xdist-1.20.1, forked-0.2, django-3.1.2, cov-2.5.1
collected 2 items
fullname.py::test_contact_full_name PASSED [ 50%]
fullname.py::test_only_second_name FAILED [100%]
================================== FAILURES ===================================
____________________________ test_only_second_name ____________________________
def test_only_second_name():
> assert Contact(None, None, None, "Simpson").full_name == "Simpson"
E AssertionError: assert ' & Simpson' == 'Simpson'
E - & Simpson
E ? ---
E + Simpson
fullname.py:83: AssertionError
===================== 1 failed, 1 passed in 0.37 seconds ======================
即该属性返回" & Simpson"
,而不是第一个断言的预期"Simpson"
。
要解决此问题,我们可以使full_name
属性也处理这种增加的复杂性,或者..我们可以在其他地方解决该问题,例如在__init__
中:
class Contact(object):
def __init__(self, a, b, c, d):
self.first_name1 = a
self.last_name1 = b
self.first_name2 = c
self.last_name2 = d
if not a and not b:
# if no name1, then put name2 into name1 and set name2 to None
self.first_name1 = self.first_name2
self.last_name1 = self.last_name2
self.first_name2 = self.last_name2 = None
再次运行pytest表明这已修复了第二个测试。
您当然不能在Django模型中提供自己的__init__
来解决此问题,但是如果您覆盖save(..)
方法,则可以执行类似的操作:
def save(self, *args, **kwargs):
if not self.first_name1 and not self.last_name1:
self.first_name1 = self.first_name2
self.last_name1 = self.last_name2
self.first_name2 = self.last_name2 = None
super(Contact, self).save(*args, **kwargs)