django模型的字段有什么类似getter和setter的东西吗?
例如,我有一个文本字段,我需要在它被保存之前进行字符串替换(在管理面板中,对于插入和更新操作),并在每次读取时进行另一个不同的替换。这些字符串替换是动态的,需要在保存和读取时完成。
当我使用python 2.5时,我无法使用python 2.6 getters / setters。
任何帮助?
答案 0 :(得分:25)
您还可以覆盖setattr和getattr。例如,假设您想要将字段标记为脏,您可能会这样:
class MyModel:
_name_dirty = False
name = models.TextField()
def __setattr__(self, attrname, val):
super(MyModel, self).__setattr__(attrname, val)
self._name_dirty = (attrname == 'name')
def __getattr__(self, attrname):
if attrname == 'name' and self._name_dirty:
raise('You should get a clean copy or save this object.')
return super(MyModel, self).__getattr__(attrname)
答案 1 :(得分:8)
您可以向要保存的模型添加pre_save
signal handler,在将值保存到数据库之前更新这些值。
它与setter函数不完全相同,因为在保存值之前,值将保持不正确的格式。如果这对您的情况来说是可接受的折衷方案,那么信号是最简单的方法,无需解决Django的ORM问题。
修改强> 在您的情况下,标准Python属性可能是这样做的方式。有一个long standing ticket可以为Django添加正确的getter / setter支持,但这不是一个简单的问题需要解决。
您可以使用this blog post
中的技巧将属性字段添加到管理员答案 2 :(得分:4)
覆盖 setattr 是一个很好的解决方案,除了这会导致从数据库初始化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()
秘密是' attrname in self .__ dict __ '。当模型从 __ dict __ 中的new或hydrated初始化时!
答案 3 :(得分:0)
在研究问题时,我遇到了使用property
装饰器的解决方案。
例如,如果您有
class MyClass(models.Model):
my_date = models.DateField()
您可以将其变成
class MyClass(models.Model):
_my_date = models.DateField(
db_column="my_date", # allows to avoid migrating to a different column
)
@property
def my_date(self):
return self._my_date
@my_date.setter
def my_date(self, value):
if value > datetime.date.today():
logger.warning("The date chosen was in the future.")
self._my_date = value
并避免任何迁移。
来源:https://www.stavros.io/posts/how-replace-django-model-field-property/