2012-02-09 19 views
6

Digamos que tengo estos dos modelos:inlines Validar antes de guardar el modelo

class Distribution(models.Model): 
    name = models.CharField(max_length=32) 

class Component(models.Model): 
    distribution = models.ForeignKey(Distribution) 
    percentage = models.IntegerField() 

y estoy usando un simple TabularInline para mostrar Component s dentro de la forma Distribution admin:

class ComponentInline(admin.TabularInline): 
    model = Component 
    extra = 1 

class DistributionAdmin(admin.ModelAdmin): 
    inlines = [ComponentInline] 

Por lo tanto, mi objetivo es validar si los porcentajes de todos los Component s de Distribution suman 100 antes de guardarlo. Suena simple, por lo que hice:

# ... Inside the Distribution model 
def clean(self): 
    # Sum of components must be 100 
    total_sum = sum(comp.percentage for comp in self.component_set.all()) 
    if total_sum != 100: 
     raise ValidationError('Sum of components must be 100%') 

Pero esto no va a funcionar el trabajo, ya que en Django todos los objetos se guardan antes de guardar sus objetos de clave externa o relacionados Many2Many, esto no es un defecto, que tiene una razón: no puede guardar primero los objetos relacionados, porque el objeto con el que están relacionados no tiene un id definido aún (id es None hasta que el objeto se guarda por primera vez en el DB).

Estoy seguro de que no soy el primero en tener este problema. Entonces, ¿hay alguna manera de lograr lo que estoy tratando de hacer? Estaba pensando en tal vez un truco de administrador usando TabularInline o ModelAdmin ...?

Respuesta

3

He aquí una idea (no probado), si estás dispuesto a mover la validación del modelo para el juego de formularios en línea:

Subclase BaseInlineFormSet y reemplazar el método limpio para comprobar la suma de los porcentajes.

from django.forms.models import BaseInlineFormSet 
from django.core.exceptions import ValidationError 

class ComponentInlineFormSet(BaseInlineFormSet): 

    def clean(self): 
     """Check that sum of components is 100%""" 
     if any(self.errors): 
      # Don't bother validating the formset unless each form is valid on its own 
      return 
     total_sum = sum(form.cleaned_data['percentage'] for form in self.forms) 
     if total_sum != 100: 
      raise ValidationError('Sum of components must be 100%') 

continuación, utilizar el juego de formularios en línea en el ComponentInline.

class ComponentInline(admin.TabularInline): 
    model = Component 
    extra = 1 
    formset = ComponentInlineFormSet 
+0

¡Esta es una buena idea! Sabía que los Inlines tenían mucho para ofrecer. Voy a intentar esto bien, ¡sé – juliomalegria

+0

genial! Funcionó muy bien con un par de cambios. Gracias, realmente :) – juliomalegria

+0

Me alegro de que funcionó :) – Alasdair

Cuestiones relacionadas