在Models.py中保存之前在ManyToManyField上进行验证

时间:2010-06-16 10:26:21

标签: python django validation admin

我有以下型号:

class Application(models.Model):
 users = models.ManyToManyField(User, through='Permission')
 folder = models.ForeignKey(Folder)

class Folder(models.Model):
 company = models.ManyToManyField(Compnay)

class UserProfile(models.Model):
 user = models.OneToOneField(User, related_name='profile')
 company = models.ManyToManyField(Company)

我想做的是检查应用程序的某个用户是否与应用程序(通过文件夹)具有相同的公司。如果是这种情况,则不应保存Application实例。

问题是,在“保存后”信号之后,ManyToManyFields才会更新。
唯一的选择似乎是新的m2m_changed信号。但是我不确定我如何回滚已经发生的豁免 另一个选择是重写保存功能(在models.py中,因为我在这里谈论管理员),但我不确定如何访问manytomanyfield内容。
最后,我已经阅读了一些关于在admin.py中重写模型管理员中的保存功能的内容,但是我仍然不知道如何访问manytomanyfield内容。

我一直在寻找这个,但我遇到的任何东西似乎对我都有用 如果有任何不清楚的地方,请告诉我。

感谢您的帮助!
Heleen

2 个答案:

答案 0 :(得分:1)

因为我没有收到Botondus的回复,所以我决定在Django Users Google Group中提出一个新问题,最后得到了jaymz的答案。

我认为Botondus方法是正确的方法,它只是不太有用。它在这种情况下不起作用的原因是因为我在字段中使用了穿透模型,我想对其进行验证。由于我之前发布的一些问题得到了反馈,我首先收集了应用程序实例,然后保存了ManyToMany实例(我相信这是正确的,但如果我错了,请纠正我)。所以我想,如果我在Through模型中对ManyToMany字段执行验证,这不会阻止保存Application实例。但实际上它确实可以防止这种情况发生。

因此,如果您的模型管理员中有一个ManyToMany字段内联,并且您想对该字段进行验证,则在直通模型中指定clean函数,如下所示:

admin.py
class PermissionInline(admin.TabularInline):
    form = PermissionForm
    model = Permission
    extra = 3

forms.py
class PermissionForm(forms.ModelForm):
    class Meta:
        model = Permission

    def clean(self):
        cleaned_data = self.cleaned_data
        user = cleaned_data['user']
        role = cleaned_data['role']
        if role.id != 1:
            folder = cleaned_data['application'].folder
            if len(filter(lambda x:x in user.profile.company.all(),folder.company.all())) > 0: # this is an intersection
                raise forms.ValidationError("One of the users of this Application works for one of the Repository's organisations!")
        return cleaned_data 

如果验证导致错误NOTHING(既没有应用程序实例也没有多个用户实例),那么您就有机会纠正错误。

答案 1 :(得分:0)

<强> forms.py

class ApplicationForm(ModelForm):
    class Meta:
        model = Application

    def clean(self):
        cleaned_data = self.cleaned_data
        users = cleaned_data['users']
        folder = cleaned_data['folder']
        if users.filter(profile__company__in=folder.company.all()).count() > 0:
            raise forms.ValidationError('One of the users of this Application works in one of the Folder companies!')
        return cleaned_data

<强> admin.py

class ApplicationAdmin(ModelAdmin):
    form = ApplicationForm

修改:用表单验证替换了初始(错误)模型验证示例。