停止在django中保存的M2M关系

时间:2012-01-22 16:37:05

标签: django

我有一个AdminModel,允许用户保存任何留空的字段。但是,当所有字段都为空时,我不希望它们能够保存。我使用以下方法实现了这个:

def save_model(self, request, obj, form, change):
    if form.has_changed():
        obj.save()
    else:
        pass

但是,Model与另一个Model有M2M关系,所以当我点击save时出现以下错误:

instance needs to have a primary key value before a many-to-many relationship can be used.

我需要在此方法中添加什么来阻止它尝试创建M2M关系?

修改

我添加了hacky解决方法,但我有兴趣知道是否有更好的方法。解决方法是更改​​else,以便更改ModelAdmin的字段属性,使其不包含M2M关系的字段 - 这可以防止它尝试建立关系。这不仅是hacky,而且只有在未能保存模型一次并抛出错误后才能工作......

2 个答案:

答案 0 :(得分:3)

你不能在save_m2m之后调用save_model。文档特别说这个钩子是not for veto purposes.

  

ModelAdmin.save_model()和ModelAdmin.delete_model()必须保存/删除   对象,它们不是为了否决的目的,而是它们允许你   执行额外的操作。

您需要的是表单验证以防止save_model触发。不知何故,您需要检测何时所有字段都留空。

class MyForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def clean(self):
        if not any(self.cleaned_data.values()):
            raise forms.ValidationError("All fields cannot be blank!")
        return self.cleaned_data

class MyAdmin(admin.ModelAdmin):
    form = MyForm

答案 1 :(得分:2)

最好在表单级别而不是管理级别进行验证。为此,请创建一个由Form使用的自定义ModelAdmin类。因此,请创建forms.py

from myapp.models import MyModel
from django import forms

class MyModelForm(forms.ModelForm):
    pass

    class Meta:
        model = MyModel

    def clean(self):
        empty = True
        for field_name, field_data in self.cleaned_data.iteritems():
            if field_data:
                empty = False
        if empty:
            raise forms.ValidationError("The form cannot be empty")
        return self.cleaned_data

并允许您的管理员使用此表单。在admin.py

from myapp.forms import MyModelForm
from django.contrib import admin

class MyModelAdmin(admin.ModelAdmin):
    ...
    form = MyModelForm