django - 覆盖保存在Django InlineModelAdmin上

标签 django django-modeladmin

这个问题可能看起来类似于this one,但是不是...

我有一个像这样的模型结构:

class Customer(models.Model):
    ....

class CustomerCompany(models.Model):
    customer = models.ForeignKey(Customer)
    type = models.SmallIntegerField(....)

我正在使用InlineModels,并且有两种类型的CustomerCampany.type。所以我为CustomerCompany和ov over 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添加新记录,我仍然需要在type上显示CustomerCompanyAdminForm字段,因为我无法覆盖saveInlineModelAdmin方法,例如:
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()

使用信号也不是解决方案,因为我的信号sender将是相同的Model,所以我无法检测到哪个InlineModelAdmin发送了它,什么type必须是...

有没有一种方法可以让我在保存之前设置type字段?

最佳答案

Alasdair的答案没有错,但是它有一些痛点,可能会引起问题。首先,通过使用form作为变量名遍历表单集,您实际上覆盖了传递给form方法的值。这没什么大不了的,但是由于您可以直接从表单集中进行保存而无需提交,因此最好这样做。其次,所有重要的formset.save_m2m()都被排除在答案之外。实际的Django docs建议以下内容:

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_formset方法必须在父ModelAdmin而不是内联代码上进行操作,并且从那里开始,您无法知道实际上正在使用哪个内联代码。如果您的obj具有两个“类型”,并且所有字段都相同,那么您应该使用代理模型,并且实际上可以覆盖每个模型的save方法以自动设置适当的类型。
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)

然后,您不需要对内联进行任何特殊处理。只需更改您现有的内联管理类以使用其适当的代理模型,一切便会自行解决。

关于django - 覆盖保存在Django InlineModelAdmin上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8294889/

相关文章:

python - 无法使用pydevd-pycharm连接到远程调试服务器

Django 管理面板内容发布错误

django - 如何从 Django Admin 的 response_change 中获取自定义表单字段值?

用于显示聚合的 Django 管理界面

python - Tornado Sentry 集成

python - 我可以在pycharm的断点处进入交互模式吗

django - 使特定缓存无效

python - django admin 自定义模型管理 url

python - Wagtail ModelAdmin 出现 list_filter 错误 : FieldDoesNotExist: Region has no field named 'p'

python - 如何修复 djangos 的 decotators 错误 : Wrapped class must subclass ModelAdmin