在Django admin中自动保存外键;

时间:2018-04-09 08:57:03

标签: django django-models django-admin

我有2个型号A和B;在django Admin中创建B实例时,我希望自动添加外键。

在下面的示例中,我尝试使用自定义表单,但我还尝试在模型中使用save,但是没有引发ValidationError

我有以下代码:

在模特中:

class A(models.model):
    content = models.TextField()

Class B(models.model):
    a = models.ForeignKey(A, related_name='bs', on_delete=models.CASCADE)
    content = models.TextField()

形式:

class AdminBModelForm(forms.ModelForm):

    class Meta:
        model = B
        fields = ['content']

    def save(self, commit=True):
        obj = super().save(commit=False)
        obj.a_id = A.objects.first()
        if obj.a_id is None:
            raise ValidationError('You first need to set A')
        obj.save()
        return obj

在admin:

  class BAdmin(admin.ModelAdmin):
        model = B
        form = AdminBModelForm

错误:IntegrityError - 列" _id"中的空值违反非空约束

2 个答案:

答案 0 :(得分:3)

首先,请注意,您不应将模型对象分配给a_id字段。你可以这样做:

obj.a = A.objects.first()

或:

a = A.objects.first()
if a is not None:
    obj.a_id = a.id

接下来,如果您无法保证A.objects.first()不是None,那么您需要在clean方法中进行检查。在savesave_model方法中提出验证错误为时已晚。

class AdminBModelForm(forms.ModelForm):

    def clean(self):
        cleaned_data = super().clean()
        if not A.objects.exists():
            raise forms.ValidationError("Cannot save B until an A has been created")
        return cleaned_data

最后,在Django管理员中设置值的常用方法是覆盖save_model方法。

class BAdmin(admin.ModelAdmin):
    model = B
    fields = ['content']

    def save_model(self, request, obj, form, change):
        obj.a = A.objects.first()
        super().save_model(request, obj, form, change)

答案 1 :(得分:0)

分配A对象时出现轻微错误。试试这个:

class AdminBModelForm(forms.ModelForm):
    class Meta:
        model = B
        fields = ['content']

    def save(self, commit=True):
        obj = super(AdminBModelForm, self).save(commit=False)
        obj.a = A.objects.first() # Assigning the object reference
        if not obj.a: # No need to check for None explicitly
            raise ValidationError('You first need to set A')
        obj.save()
        return obj