django admin inline 用的同一个,其中一个是空,无法保存
在Django中,Admin是一个强大的工具,可以让开发者轻松管理数据库中的数据。其中的Inline功能可以让我们在一个页面上同时编辑多个相关联的模型。但有时候,在使用Inline的过程中会遇到一个问题:使用同一个Inline对象,但其中一个为空,导致无法保存数据。本文将详细介绍这个问题的原因和解决方法。
问题描述
假设有如下两个模型,一个是Parent,一个是Child,它们之间是一对多的关系。
from django.db import models
class Parent(models.Model):
name = models.CharField(max_length=100)
class Child(models.Model):
parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
接下来,我们在Admin中定义Inline,让Child模型能够在Parent的编辑页面中进行编辑。
from django.contrib import admin
from .models import Parent, Child
class ChildInline(admin.TabularInline):
model = Child
@admin.register(Parent)
class ParentAdmin(admin.ModelAdmin):
inlines = [ChildInline]
在这种情况下,如果我们在Parent的编辑页面中同时添加了两个Child对象,但只填写了一个Child对象的信息,另一个Child对象为空,当我们尝试保存数据时,会发现无法成功保存,页面会提示“Please correct the errors below”。
问题原因
发生这种情况的原因是Django在处理Inline数据保存时,会检查每个Inline对象是否为空。如果其中一个Inline对象为空,那么Django会默认认为这是一个错误,因为在数据库中外键字段不能为空。
解决方法
为了解决这个问题,我们可以通过重载Inline的clean
方法来处理。我们可以在ChildInline
中添加一个clean
方法,手动检查每个Inline对象是否为空,并将空的对象从数据中删除。
from django.contrib import admin
from .models import Parent, Child
class ChildInline(admin.TabularInline):
model = Child
def clean(self):
super(ChildInline, self).clean()
for form in self.forms:
if form.cleaned_data.get('id') and not form.cleaned_data.get('name'):
form.cleaned_data = {}
form.cleaned_data[self._pk_key] = None
在上面的代码中,我们重载了clean
方法,遍历每一个Inline对象的表单,如果发现其中的某个对象为空(没有填写name字段),则将该对象从数据中删除。
经过上述处理后,我们再次尝试在Parent的编辑页面上添加两个Child对象,但只填写一个Child对象的信息,另一个对象留空。此时保存数据就不会再出现错误了。这样就解决了使用同一个Inline对象时,其中一个为空导致无法保存数据的问题。
总结一下,通过重载Inline的clean
方法,手动处理空对象可以解决这个问题。