覆盖Django InlineModelAdmin上的保存
这个问题看起来很像,但不是 我的模型结构如下:覆盖Django InlineModelAdmin上的保存,django,django-modeladmin,Django,Django Modeladmin,这个问题看起来很像,但不是 我的模型结构如下: class Customer(models.Model): .... class CustomerCompany(models.Model): customer = models.ForeignKey(Customer) type = models.SmallIntegerField(....) 我使用的是InlineModels,有两种类型的CustomerCompany.type。因此,我为CustomerCompa
class Customer(models.Model):
....
class CustomerCompany(models.Model):
customer = models.ForeignKey(Customer)
type = models.SmallIntegerField(....)
我使用的是InlineModels
,有两种类型的CustomerCompany.type
。因此,我为CustomerCompany
定义了两个不同的内联线,并覆盖InlineModelAdmin.queryset
class CustomerAdmin(admin.ModelAdmin):
inlines=[CustomerCompanyType1Inline, CustomerCompanyType2Inline]
class CustomerCompanyType1Inline(admin.TabularInline):
model = CustomerCompany
def queryset(self, request):
return super(CustomerCompanyType1Inline, self).queryset(request).filter(type=1)
class CustomerCompanyType2Inline(admin.TabularInline):
model = CustomerCompany
def queryset(self, request):
return super(CustomerCompanyType2Inline, self).queryset(request).filter(type=2)
到目前为止一切都很好,但是要为InlineModelAdmin
添加新记录,我仍然需要在AdminForm
上显示CustomerCompany
的类型字段,因为我不能覆盖InlineModelAdmin
方法,比如:
class CustomerCompanyType2Inline(admin.TabularInline):
model = CustomerCompany
def queryset(self, request):
return super(CustomerCompanyType2Inline, self).queryset(request).filter(type=2)
#Following override do not work
def save_model(self, request, obj, form, change):
obj.type=2
obj.save()
使用信号也不是一个解决方案,因为我的信号发送方
将是相同的型号
,因此我无法检测哪个InlineModelAdmin
发送它,以及类型必须是什么
是否有一种方法可以让我在保存前设置类型字段?有一种方法可以重写。您必须计算出表单集
以某种方式表示哪个内联
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for instance in instances:
# Do something with `instance`
instance.save()
formset.save_m2m()
阿拉斯代尔的回答没有错,但有几个痛点可能会引起问题。首先,通过使用form
作为变量名在formset中循环,实际上覆盖了传递给form
方法的值。这没什么大不了的,但是既然可以直接从表单集中进行保存而不必提交,那么这样做更好。其次,答案中遗漏了最重要的formset.save_m2m()
。实际报告建议如下:
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for instance in instances:
# Do something with `instance`
instance.save()
formset.save_m2m()
您将遇到的问题是,save\u formset
方法必须在父级ModelAdmin
上,而不是在内联上,并且从那里无法知道实际使用的是哪个内联。如果您有一个具有两个“类型”的obj,并且所有字段都相同,那么您应该使用代理模型,并且您实际上可以覆盖每个“类型”的保存方法以自动设置适当的类型
class CustomerCompanyType1(CustomerCompany):
class Meta:
proxy = True
def save(self, *args, **kwargs):
self.type = 1
super(CustomerCompanyType1, self).save(*args, **kwargs)
class CustomerCompanyType2(CustomerCompany):
class Meta:
proxy = True
def save(self, *args, **kwargs):
self.type = 2
super(CustomerCompanyType2, self).save(*args, **kwargs)
然后,你不需要对你的内联线做任何特别的事情。只要将现有的内联管理类更改为使用适当的代理模型,一切都会自行解决。在使用save\u formset时,其他答案是正确的。但他们缺少检查当前保存的模型的方法。为此,您可以:
if formset.model == CustomerCompany:
# actions for specific model
这将使save_formset函数看起来像:(假设您只想覆盖特定模型的save)
+1使用代理模型的好方法。我更新了我的答案,修正了你提到的最明显的错误。实际上,代理模型方法消除了覆盖save\u formset
的需要。代理本身已经重写了知道如何保存为正确类型的save
方法。因此,您只需使用内联线而不必担心它。我的评论不清楚——我同意即使在解决了save\u formset
(save\u m2m
等)中的问题后,仍然存在要保存哪个内联线的问题。我知道代理模型方法避免了这一点:)谢谢,不知何故我完全忘记了ProxyModel
,它的使用将解决我的问题。。。我会在短时间内尝试它。。。谢谢,如果您计划使用权限,我建议您不要使用代理模型。到今天为止,这将代理方法转变为令人难以置信的痛苦。
def save_formset(self, request, form, formset, change):
# if it's not the model we want to change
# just call the default function
if formset.model != CustomerCompany:
return super(CustomerAdmin, self).save_formset(request, form, formset, change)
# if it is, do our custom stuff
instances = formset.save(commit=False)
for instance in instances:
instance.type = 2
instance.save()
formset.save_m2m()