2

I have a model

class Group(models.Model):
    active = models.BooleanField(null=False, blank=False, default=True)

and its admin pages

class GroupAdmin(admin.ModelAdmin):
    change_form_template = "admin/group/group.html"
    form = GroupAdminForm

    def change_view(self, request, object_id, form_url='', extra_context=None):
        extra_context = extra_context or {}
        extra_context['group_data'] = self.get_info(object_id)
        return super(GroupAdmin, self).change_view(
            request, object_id, form_url, extra_context=extra_context,
        )

class GroupAdminForm(ModelForm):
    class Meta:
        model = Group
        fields = '__all__'

    def clean_active(self):
        active = self.cleaned_data['active']

        if 'active' in self.changed_data and not active and OtherCondition:
            raise ValidationError('Group must stay active because of OtherCondition')
        return active

which requires the change_view template.

Because of the change_view template, validation errors are not showing up.

How do I throw a validation error and have it show up on Django admin? Is there a way to do this using ValidationError? Is it by changing the change_view template?

  • When I throw it on Group.save() on the Model, it breaks the page, instead of not-saving and telling the user to fix the error.
  • At first I hadn't used an AdminForm, but using it means the validation is run, and it requests a change (Please correct the error below.), but it doesn't show the ValidationError message.

This question is similar but recommends Messages, but I'd like to know if there's another way: Raise django admin validation error from a custom view


I don't think I'm including field errors specifically, but I think it should be including them through the django supplied html:

admin/change_form has

{% block field_sets %}
{% for fieldset in adminform %}
  {% include "admin/includes/fieldset.html" %}
{% endfor %}
{% endblock %}

and admin/includes/fieldset.html has {{ line.errors }}. Maybe it's to do with passing the error to the change_view?


group.html as requested.

{% extends "admin/change_form.html" %}
{%  block field_sets %}
    {# stuff #}
    {{ block.super }}
{%  endblock %}

{% block inline_field_sets %}
{% for inline_admin_formset in inline_admin_formsets %}
    {# stuff #}
{% endfor %}
{% endblock %}

{# M2M Preview #}
{% block after_related_objects %}
    {# stuff #}
{%  endblock %}

ehacinom
  • 8,070
  • 7
  • 43
  • 65
  • 1
    Can you add `group.html` here (or at least the form rendering)? If you are rendering manually, are you including the field errors? – Paulo Almeida Mar 26 '18 at 17:45
  • You're not including field errors, but as far as I can tell (I'm not familiar with that form) you're also not rendering the form manually, so that shouldn't be the problem. You could try [adding the error manually](https://docs.djangoproject.com/en/2.0/ref/forms/api/#django.forms.Form.add_error), to a specific field or as a `non_field_error`, with field `None`, just to see if it works. – Paulo Almeida Mar 26 '18 at 18:24
  • @PauloAlmeida I think you're right, it shouldn't be the problem, but I'll try adding it manually! – ehacinom Mar 26 '18 at 18:29
  • that doesn't appear to fix it – ehacinom Mar 26 '18 at 18:34
  • The only thing that occurs to me is to use a debugger and see what's the value of `line` in the template, and other related variables. – Paulo Almeida Mar 26 '18 at 20:09

1 Answers1

3

I think form validation is a good idea in these type of situations.

forms.py

class YourForm(forms.ModelForm):

    def clean(self):
        super(YourForm, self).clean()
        data1 = self.cleaned_data.get('data1')
        data2 = self.cleaned_data.get('data2')

        # Add validation condition here
        # if validation error happened you can raise the error 
        # and attach the error message with the field you want.

        self.add_error('field_name', 'error message')

In admin.py

 class YourAdminClass(admin.ModelAdmin):
     form = YourForm
Nitheesh MN
  • 608
  • 8
  • 18