Reputation: 507
I am trying to validate that the variable foo is the same for MyModel and Item before adding it as a m2m. I want to raise a ValidationError in the admin if it is not.
models.py
class Item(models.Model):
foo = models.CharField(max_length=200)
class MyModel(models.Model):
foo = models.CharField(max_length=200)
items = models.ManyToManyField(Item)
signals.py
@receiver(m2m_changed, sender=MyModel.items.through)
def my_validator(sender, instance, action, pk_set, **kwargs):
if action == 'pre_add':
if Item.objects.filter(id__in=pk_set, foo=instance.foo).count() != len(pk_set):
raise ValidationError({'items': ["Foo doesn't match"]})
Is there a way for the ValidationError to show up properly in the admin and not as a 500 error.
I wasn't able to come up with a solution to use MyModel's clean method to validate the same value of foo. Any advice is appreciated.
Upvotes: 4
Views: 1822
Reputation: 5242
Create a form
class with clean
method and modify your admin class to use the form. Read this:
Like:
@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
search_fields = ('foo', 'items__foo')
list_display = ('foo', 'items__foo')
form = MyModelForm
class MyModelForm(forms.ModelForm):
def clean(self):
"""
This is the function that can be used to
validate your model data from admin
"""
super(MyModelForm, self).clean()
foo = self.cleaned_data.get('foo')
pk_set = Item.objects.all().values_list("id")
# The logic you were trying to filter..
if Item.objects.filter(id__in=pk_set).count() != len(pk_set):
raise ValidationError({'items': ["Foo doesn't match"]})
Upvotes: 5