使用属性修改模型字段Django

时间:2013-12-09 10:23:06

标签: django python-2.7 django-models

我有如下图所示的模型字段: -

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)与用户模型有一对多关系,只是为了清楚我的问题。

2 个答案:

答案 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的值。