我有以下型号:
class Placement(models.Model):
name = models.CharField(max_length=500, blank=False)
actual_start_date = models.DateField(blank=True, null=True)
actual_end_date = models.DateField(blank=True, null=True)
include_in_conversion_count = models.BooleanField(blank=False, null=False, default=True)
我希望只有当new actual_start_date早于db中注册的actual_start_date时才能使用save()来更改actual_start_date。
所以我尝试更改了save和 init 方法:
def __init__(self, *args, **kwargs):
super(Placement, self).__init__(*args, **kwargs)
if hasattr(self, 'actual_start_date'):
self.__original_actual_start_date = self.actual_start_date
if hasattr(self, 'actual_end_date'):
self.__original_actual_end_date = self.actual_end_date
def save(self, *args, **kwargs):
if self.pk is None:
super(Placement, self).save(*args, **kwargs)
else:
if hasattr(self, 'actual_start_date') & hasattr(self, '__original_actual_start_date'):
self.actual_start_date = min(self.actual_start_date, self.__original_actual_start_date)
if hasattr(self, 'actual_end_date') & hasattr(self, '__original_actual_end_date'):
self.actual_end_date = max(self.actual_end_date, self.__original_actual_end_date)
super(Placement, self).save(*args, **kwargs)
启动服务器时控制台中没有任何错误,我可以读取/更新/保存对象。但是,当我尝试测试它时,它不起作用。即使在旧对象后面有一个新的actual_start_date,也会保存该对象。
from sizmek_tag_manager.models import Placement
pl = Placement.objects.get(pk = 5473828)
pl.actual_start_date
返回datetime.date(2015,12,31)
pl.actual_start_date = datetime.date(2016, 1, 1)
pl.save()
pl = Placement.objects.get(pk = 5473828)
pl.actual_start_date
返回datetime.date(2016,1,1)
那么我做错了什么?
答案 0 :(得分:1)
如果您可以将现有对象与要保存的对象进行比较,为什么使用hasAttr
?只需获取当前版本并检查新actual_start_date
是否符合您的要求:
class Placement(models.Model):
#fields and other stuff
def save(self, *args, **kwargs):
if self.pk is not None:
current = Placement.objects.get(pk=self.pk)
#and here check the requirement
if self.actual_start_date < current.actual_start_date:
super(Placement, self).save(*args, **kwargs)
#else:
# raise exception or sth
else:
super(Placement, self).save(*args, **kwargs)
答案 1 :(得分:-1)
问题的根本原因是提供类私有变量的双下划线。来自python 2 docs
具有双前导下划线的变量名称被“修改”以提供一种简单但有效的方法来定义类私有变量。表单__spam的任何标识符(至少两个前导下划线,最多一个尾随下划线)在文本上用_classname__spam替换,其中classname是当前的类名,其中任何前导下划线都被剥离。
这不保证隐私:外部用户仍然可以故意访问“_classname__spam”属性,私有值在对象的 dict 中可见。许多Python程序员根本不打算使用私有变量名。
因此,解决方案将是
使用单个下划线变量名称
使用hasattr(Property, '_Property____original_actual_start_date'
)
E.g:
class Foo(object):
def __init__(self, debug=False):
self._foo = '_foo'
self.__foo = '__foo'
self.debug = debug
def has_foo_property_with_prefix(self, prefix):
property_name = ''.join([prefix, 'foo'])
has_property = hasattr(self, property_name)
if self.debug:
print('has %s property? %s' % (property_name, has_property))
return has_property
if __name__ == '__main__':
f = Foo(debug=True)
assert True == f.has_foo_property_with_prefix('_')
assert False == f.has_foo_property_with_prefix('__')
assert True == f.has_foo_property_with_prefix('_Foo__')