Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
覆盖Django InlineModelAdmin上的保存_Django_Django Modeladmin - Fatal编程技术网

覆盖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()