Jia*_*aro 37 python django model properties
我认为问这个问题的最好方法是使用一些代码......我可以这样做吗?(编辑:答案:不)
class MyModel(models.Model):
foo = models.CharField(max_length = 20)
bar = models.CharField(max_length = 20)
def get_foo(self):
if self.bar:
return self.bar
else:
return self.foo
def set_foo(self, input):
self.foo = input
foo = property(get_foo, set_foo)
Run Code Online (Sandbox Code Playgroud)
或者我必须这样做:
class MyModel(models.Model):
_foo = models.CharField(max_length = 20, db_column='foo')
bar = models.CharField(max_length = 20)
def get_foo(self):
if self.bar:
return self.bar
else:
return self._foo
def set_foo(self, input):
self._foo = input
foo = property(get_foo, set_foo)
Run Code Online (Sandbox Code Playgroud)
注意:通过将db_column传递给模型字段,可以将列名保留为数据库中的'foo'.当您处理现有系统并且不希望无缘无故地进行数据库迁移时,这非常有用
And*_*ler 20
模型字段已经是属性,所以我想你必须以第二种方式来避免名称冲突.
当您定义foo = property(..)时,它实际上会覆盖foo = models ..行,因此该字段将不再可访问.
您需要为属性和字段使用不同的名称.实际上,如果你按照示例#1中的方式执行它,当你尝试访问属性时,你会得到一个无限循环,因为它现在试图返回它自己.
编辑:也许您还应该考虑不使用_foo作为字段名称,而是使用foo,然后为您的属性定义另一个名称,因为属性不能在QuerySet中使用,因此当您执行某个操作时,您需要使用实际的字段名称过滤器例如.
Yau*_*ich 17
如上所述,实现自己的django.db.models.Field类的正确替代方法,应该使用 - db_column参数和自定义(或隐藏)类属性.我只是在@Jiaaro的编辑中重写代码,遵循python中更严格的OOP约定(例如,如果_foo实际上应该被隐藏):
class MyModel(models.Model):
__foo = models.CharField(max_length = 20, db_column='foo')
bar = models.CharField(max_length = 20)
@property
def foo(self):
if self.bar:
return self.bar
else:
return self.__foo
@foo.setter
def foo(self, value):
self.__foo = value
Run Code Online (Sandbox Code Playgroud)
__foo将被解析为_MyModel__foo(由dir(..)看到)因此隐藏(私有).请注意,此表单还允许使用@property装饰器,这最终是编写可读代码的更好方法.
同样,django将创建带有两个字段foo和bar的*_MyModel表.
之前的解决方案受到影响,因为@property导致admin和.filter(_foo)出现问题.
更好的解决方案是覆盖setattr,但这会导致从DB初始化ORM对象时出现问题.然而,有一个解决这个问题的技巧,它是普遍的.
class MyModel(models.Model):
foo = models.CharField(max_length = 20)
bar = models.CharField(max_length = 20)
def __setattr__(self, attrname, val):
setter_func = 'setter_' + attrname
if attrname in self.__dict__ and callable(getattr(self, setter_func, None)):
super(MyModel, self).__setattr__(attrname, getattr(self, setter_func)(val))
else:
super(MyModel, self).__setattr__(attrname, val)
def setter_foo(self, val):
return val.upper()
Run Code Online (Sandbox Code Playgroud)
秘密是' 自我中的名字.__ dict__ '.当模型从__dict__初始化为new或hydrated时!
| 归档时间: |
|
| 查看次数: |
29528 次 |
| 最近记录: |