我有2个模型所有者和物品。
class Owner(admin.ModelAdmin):
is_active = models.BooleanField(default=False)
class Item(admin.ModelAdmin):
owner = models.ForeignKey(Owner, related_name='items', on_delete=models.CASCADE)
is_active = models.BooleanField(default=False)
遵守以下规则:
1)如果所有者is_active
为False
,则Item
无法生效
2)如果Owner
is_active
True
变为False
Item(s)
,则is_active
False
变为def clean(self):
super().clean()
if self.is_active:
if not self.owner.is_active:
raise ValidationError(
{'is_active': 'The Owner need to be checked an validated first'})
return self.is_active
规则1,在项目模型中:
def save(self, *args, **kwargs):
# if the active state was changed and is False
if self.__original_is_active != self.is_active and self.is_active is False:
# update does direct changes in database doesn't call save or signals
self.items.update(is_active=False)
super().save(*args, **kwargs)
规则2,在模型中:(在stackoverflow的帮助下):
Item Model
问题:
我在Owner Admin
中添加了TabularInline
is_active
。
对于规则2,当我将Owner
True
从False
切换到is_active
并尝试保存时,会出现Rule1(ValidationError),但不能保存。
这对我来说很奇怪,因为产品Owner Form
的更新是在is_active
保存之前完成的,所以它应该具有以前的值。
我认为Item
的{{1}}已更新为False
,但在保存尝试时再次True
(因为在UI中保持这种方式),但是我不知道如何解决它。
答案 0 :(得分:1)
在Django admin中,当您保存表单时。首先验证它,然后调用save方法。
您可以覆盖默认的django表单。例如:
class CompanyAdminForm(forms.ModelForm):
def clean(self):
self.instance.products.update(is_active=False)
return self.cleaned_data
class CompanyAdmin(admin.ModelAdmin):
form = CompanyAdminForm
或者您可以将产品清洁方法更改为
def clean(self):
super().clean()
if self.is_active and not self.company.is_active:
self.is_active = False
return self.is_active
答案 1 :(得分:1)
我已转载您的问题并进行了测试。经过一些调试后,我发现以下内容
问题
保存Owner
模型时,管理表单会对其进行验证并对其执行full_clean
。在模型实例上调用full_clean
时,无论是否将其保存在db中,都会为其分配更新的值。这意味着“所有者”的is_active
值现在为False(但尚未保存在db中)。
在将此实例保存到db之前,django admin会清除所有表单集实例并为它们分配新值(如果有更新)。这就是您要验证Item
实例的地方。
已更新(但未保存在db中)所有者已分配给所有Item
实例。而且这里的代码失败,因为Item
实例已更新了所有者实例,而所有者实例已更新了is_active
的值。
解决方案
我建议您使用相同的技巧进行条件检查,就像检查所有者的is_active
的值是否已更改一样。只需将__original_is_active
字段从私有更改为受保护,然后将其用于验证即可
def clean(self):
super().clean()
if self.is_active:
if not self.owner._original_is_active:
raise ValidationError(
{'is_active': 'The Owner need to be checked an validated first'})
return self.is_active
所有者实例将具有is_active
的更新值,但还具有缓存在_original_is_active
中的初始值。
我希望这能解决您的困惑和问题。