I have the following models:
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)
What I would like to do is to check whether one of the users of the Application has the same company as the Application (via Folder). If this is the case the Application instance should not be saved.
The problem is that the ManyToManyFields aren't updated until after the 'post-save' signal.
The only option seems to be the new m2m_changed signal. But I'm not sure how I then roll back the save that has already happened. Another option would be to rewrite t开发者_JAVA百科he save function (in models.py, because I'm talking about the admin here), but I'm not sure how I could access the manytomanyfield content. Finally I've read something about rewriting the save function in the admin of the model in admin.py, however I still wouldn't know how you would access the manytomanyfield content.I have been searching for this everywhere but nothing I come across seems to work for me.
If anything is unclear, please tell me.Thanks for your help!
HeleenBecause I didn't get a reply from Botondus I decided to ask a new question in the Django Users Google Group and finally got the answer from jaymz.
I figured that Botondus method was the right way of doing it, it just wasn't quite working. The reason that it doesn't work in this case is because I'm using a Through model for the field I would like to do the validation on. Because of some earlier feedback I got on a previously posted question I gathered that first the Application instance is saved and then the ManyToMany instances are saved (I believe this is right, but correct me if I'm wrong). So I thought that, if I would perform the validation on the ManyToMany Field in the Through model, this would not prevent the Application instance being saved. But in fact it does prevent that from happening.
So if you have a ManyToMany Field inline in your model's admin and you would like to do validation on that field, you specify the clean function in the through model, like this:
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
If the validation results in an error NOTHING (neither the application instance, nor the manytomany users instances) is saved and you get the chance to correct the error.
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
Edit: Replaced initial (wrong) model validation example with form validation.
精彩评论