¿Cuál es la forma correcta de validar ManyToManyFields?

Si tengo un modelo con ManyToManyField y quiero restringirlo a instancias que tienen una propiedad en particular, ¿cuál es la mejor manera de hacerlo? Puedo hacerlo en la validación del formulario o en la vista, pero me gustaría hacerlo más cerca del modelo.

Por ejemplo, ¿cómo puedo permitir que solo las instancias de clase B que tienen is_cool establecido en True se asocien con instancias de clase A?

from django.db import models

class A(models.Model):
    cool_bees = models.models.ManyToManyField('B') 

class B(models.Model):
    is_cool = models.BooleanField(default=False)

preguntado el 01 de julio de 12 a las 08:07

@okm ¡Nooooo, me quitaste los espacios de McConnell! Y no trate de sacarme PEP 8 porque no dice nada sobre definiciones, solo sobre llamadas a funciones. ;) -

1 Respuestas

Para estar más cerca del modelo, puede usar la señal m2m_changed para verificar si el modelo cumple con sus requisitos, por lo que el código podría verse así:

import django.db.models.signals

def validate(sender, instance, action, reverse, model, pk_set, **kwargs):
    if action == "pre_add":
        # if we're adding some A's that're not cool - a.cool_bees.add(b)
        if not reverse and model.objects.filter(pk__in=pk_set, is_cool=False):
              raise ValidationError("You're adding an B that is not cool")
        # or if we add using the reverse - b.A_set.add(a)
        if reverse and not instance.is_cool:
              raise ValidationError("You cannot insert this non-cool B to A")


signals.m2m_changed.connect(validate, sender=A.cool_bees.through)

Respondido 01 Jul 12, 11:07

Gracias. ¿Hay alguna manera de hacerlo con la validación del modelo? Si genero un 'Error de validación' aquí, tendré que detectarlo yo mismo. No es que eso sea una dificultad, pero esperaba mantener las cosas en un solo lugar. - aptwebapps

Los cambios de m2m no se realizan en model.save, por lo que sería difícil agregarlos en la validación del modelo. Sin embargo, puede establecer una propiedad de modelo egais_valid en lugar de generar ValidationError y omitir elementos incorrectos, luego verificarlo más tarde en la validación del modelo, pero de esta manera podría ocultar algunos errores... - tisho

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.