#12780: Provide a hook for compound form/formset validation in ModelAdmin
-------------------------------+---------------------------------------
     Reporter:  mrts           |                    Owner:  Ramez Issac
         Type:  New feature    |                   Status:  assigned
    Component:  contrib.admin  |                  Version:  dev
     Severity:  Normal         |               Resolution:
     Keywords:                 |             Triage Stage:  Accepted
    Has patch:  1              |      Needs documentation:  0
  Needs tests:  0              |  Patch needs improvement:  0
Easy pickings:  0              |                    UI/UX:  0
-------------------------------+---------------------------------------
Changes (by Natalia Bidart):

 * cc: Carlton Gibson, Natalia Bidart, Mariusz Felisiak (added)


Comment:

 In order to properly review the PR, I've been investigating solutions for
 this ticket, and as I mentioned in
 [[https://github.com/django/django/pull/16777|PR #16777]], I think there
 is currently enough flexibility in overriding the inline's formset so that
 any custom validation involving both the parent form/instance and the
 formset themselves can be done there. Following the example referenced in
 the ticket description use case, in order to block `Clip` instances to be
 approved without a matching `ClipDescription` in the same language, the
 customization would look similar to this:

 {{{
 # models.py
 from django.db import models


 LANGS = ['de', 'en', 'es', 'fr', 'it']


 class Clip(models.Model):
     is_approved = models.BooleanField(default=False)
     language = models.CharField(choices=[(i, i) for i in LANGS],
 max_length=2)


 class ClipDescription(models.Model):
     clip = models.ForeignKey(Clip, on_delete=models.CASCADE)
     text = models.TextField()
     language = models.CharField(choices=[(i, i) for i in LANGS],
 max_length=2)
 }}}

 {{{
 # admin.py
 from django import forms
 from django.contrib import admin
 from django.core.exceptions import ValidationError

 from .models import Clip, ClipDescription


 class InlineFormset(forms.models.BaseInlineFormSet):
     def clean(self):
         languages = {
             f.cleaned_data['language']
             for f in self.forms
             if 'language' in f.cleaned_data
             # This next line filters out inline objects that did exist
             # but will be deleted if we let this form validate --
             # obviously we don't want to count those if our goal is to
             # enforce a condition of related objects.
             and not f.cleaned_data.get('DELETE', False)
         }
         if (
             self.instance.is_approved
             and self.instance.language not in languages
         ):
             raise ValidationError(
                 'A Clip cannot be approved without a description in the
 same language'
             )


 class ClipDescriptionInline(admin.TabularInline):
     model = ClipDescription
     formset = InlineFormset


 class ClipAdmin(admin.ModelAdmin):
     inlines = [
         ClipDescriptionInline,
     ]


 admin.site.register(Clip, ClipAdmin)
 }}}

 In summary, I'm proposing to close this issue as invalid/wontfix, but I'd
 live to know what others think first.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/12780#comment:13>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/01070187e7c9e650-8c13d8b1-349c-4e7d-9d27-3c39cdfb7b62-000000%40eu-central-1.amazonses.com.

Reply via email to