2013-12-09 43 views
2

我有模型字段,如下图所示: -使用属性来修改模型字段的Django

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没有被评估并且因此_企业字段不被更新。

那么我该怎么做才能使它工作?这里最好的方法是什么?

我有另一个模型(CorporateUser)与用户模型的一对多关系,只是为了清晰我的问题。

回答

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) 

注意值是如何传递给制定者。它不应该像你那样在那里计算。如果您需要自动更新企业价值,那么您不需要财产,您应该覆盖模型.save()方法或聆听它的pre_save信号并在那里更新字段。

其次,你不应该有条件地设置setter。 Setter应该始终将属性设置为传递的值。就像这样:

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? 

第三,你不应该分配给listCharField。这应该如何工作?它可能会将其串联起来。

第四,你甚至没有分配一个列表,你正在分配查询集,这是更糟。

第五,你在两行中执行两次基本相同的数据库请求。检查的有效途径,如果是空的,然后分配是通过重用相同的查询集:

corporates = self.user.corporateuser_set.values_list('company', flat=True) 
if corporates: 
    # Stringify it explicitly and our way 
    self._corporate = ','.join(corporates) 
+0

'违反这条规则你会引起悲伤:'什么 规则? – user2454305

+0

安装员应无条件设置。 – Suor

+0

为了您的解释,我接受您的答案。它很详细,但我不同意使用save()的选项。我认为最好的方法是使用财产虚拟领域。它似乎现在工作良好,不知道它的效率是否会持续下去:-) – user2454305

0

这不是你如何使用属性。 property function的第一个参数,如果你这样使用的话,那就是getter方法。你甚至没有提供一个getter方法。你需要一个返回值self._corporate

+0

我添加getter方法作为'高清get_corporate(个体经营): 如果self._corporate: 回报self._corporate'然后我编辑了我的财产功能到'企业=财产(get_corporate,set_corporate)'但即使这样做它没有工作!我是否还想念一些东西? – user2454305