【问题标题】:Using properties to modify model field Django使用属性修改模型字段 Django
【发布时间】:2013-12-26 10:00:44
【问题描述】:

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

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)与用户模型具有一对多关系。

【问题讨论】:

    标签: django python-2.7 django-models


    【解决方案1】:

    你在很多方面都做错了。

    首先,属性在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 应始终将属性设置为传递的值。像这样:

    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)
    

    【讨论】:

    • '违反这条规则会导致悲痛:'什么规则?
    • Setter 应该无条件设置。
    • 为了您的解释,我接受您的回答。它非常详细,但我不同意使用 save() 的选项。我认为最好的方法是使用属性虚拟字段。它现在似乎运作良好,但不确定它的效率是否会持续:-)
    【解决方案2】:

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

    【讨论】:

    • 我将 getter 方法添加为 def get_corporate(self): if self._corporate: return self._corporate 然后我将我的属性函数编辑为 corporate = property(get_corporate, set_corporate) 但即使这样它也没有工作!我还缺少什么吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 2016-10-12
    • 2022-01-24
    • 1970-01-01
    • 2010-11-30
    • 2020-07-23
    • 2019-06-23
    相关资源
    最近更新 更多