我有如下图所示的模型字段: -
user=models.ForeignKey(CustomUser, null=True)
_corporate = models.CharField(max_length=10, null=True, db_column='corporate')
def set_corporate(self,value):
if self.user.corporateuser_set.all():
self._corporate = self.user.corporateuser_set.values_list('company', flat=True)
corporate= property(set_corporate)
不知何故,set_corporate未被评估,因此_corporate字段未更新。
那么我该怎么做才能让它发挥作用?这里最好的方法是什么?
我有另一个模型(CorporateUser)与用户模型有一对多关系,只是为了清楚我的问题。
答案 0 :(得分:3)
你在很多方面做错了。
首先,在python中以这种方式使用属性:
class A:
@property
def foo(self):
return self._foo
@foo.setter
def foo(self, value):
self._foo = value
或者这样:
class A:
def get_foo(self):
return self._foo
def set_foo(self, value):
self._foo = value
foo = property(get_foo, set_foo)
注意如何将值传递给setter。它不应该像你那样在那里计算。如果您需要自动更新公司价值,那么您不需要属性,您应该覆盖模型.save()
方法或在那里收听其pre_save
信号和更新字段。
其次,你不应该有条件地设置setter。 Setter应始终将property设置为值传递。像这样:
def set_corporate(self, value):
# If the list is empty then corporate becomes empty
self._corporate = \
self.user.corporateuser_set.values_list('company', flat=True)
违反这条规则会导致悲伤:
obj.corporate = 'hi'
# obj.corporate is now 'hi'
obj.corporate = ''
# obj.corporate is still 'hi'. WTF?
第三,您不应将list
分配给CharField
。这应该怎么样?它可能会将其字符串化。
第四,你甚至没有分配一个列表,你正在分配查询集,这更糟糕。
第五,你在两行中做了两次基本相同的数据库请求。检查是否为空然后分配的有效方法是重用相同的查询集:
corporates = self.user.corporateuser_set.values_list('company', flat=True)
if corporates:
# Stringify it explicitly and our way
self._corporate = ','.join(corporates)
答案 1 :(得分:0)
这不是你如何使用属性。 property
function的第一个参数,如果您使用它,就是 getter 方法。你甚至没有提供一个getter方法。您需要一个返回self._corporate
的值。