How to implement clean() for a model with ManyToMany fields?

3,964 views
Skip to first unread message

Carsten Fuchs

unread,
Oct 29, 2012, 11:01:00 AM10/29/12
to django...@googlegroups.com
Hi all,

using Django 1.3.1, I use a model like this:


class KalenderEintrag(models.Model):
id = models.AutoField(primary_key=True)
von = models.DateField(verbose_name=u"\u200Bvon")
bis = models.DateField(verbose_name=u"\u200Bbis")
text = models.CharField(max_length=80)
farbe = models.CharField(max_length=20, blank=True)
regionen = models.ManyToManyField(Region, null=True, blank=True)
kstellen = models.ManyToManyField(Kostenstelle, null=True, blank=True)
bereiche = models.ManyToManyField(Bereich, null=True, blank=True)

def clean(self):
if not self.regionen and not self.kstellen and not self.bereiche:
raise ValidationError("This calender entry won't be
displayed anywhere.")


What I would like to do in clean() is making sure that not all three
ManyToMany fields are empty/blank all at the same time.

However, it doesn't work as shown above:

With pre-existing KalenderEintrag entries whose regionen, kstellen and
bereiche are all empty, the "if not self.regionen and not ..." does not
trigger.

When I try to newly create a KalenderEintrag in the admin, the "if not
self.regionen and not ..." line raises a ValueError exception:
"'KalenderEintrag' instance needs to have a primary key value before a
many-to-many relationship can be used."

How can I properly implement clean() to check the three ManyToMany
fields for non-empty contents?

Best regards,
Carsten



--
Cafu - the open-source Game and Graphics Engine
for multiplayer, cross-platform, real-time 3D Action
Learn more at http://www.cafu.de

Martin J. Laubach

unread,
Oct 29, 2012, 3:15:43 PM10/29/12
to django...@googlegroups.com
Basically, you can't. M2m fields are saved after the model is saved, so you either get objects that are not yet ready for that check (as you experienced) or you will test the previous value of the m2m field, neither of which is what you want.

You can modify the admin interface and do the validation in the AdminForm, or perhaps catch the m2m_changed signal and do some checks there, but you can't do the validation you want in the clean method.

    mjl



Carsten Fuchs

unread,
Oct 30, 2012, 1:03:45 PM10/30/12
to django...@googlegroups.com
Hi Martin,

thank you very much for your very clear and prompt help!

:-)

Best regards,
Carsten

John Lawlor

unread,
Oct 17, 2015, 5:56:32 PM10/17/15
to Django users
You can, however, override the clean() method in a form for this model, and in clean() you have access to the form's fields and would be able to check and compare that all three of these fields are not simultaneously blank. You would not be able to do such processing in reverse--that is, you do not have access to a KalenderEintrag field on a Region, Kostenstelle, or Bereich form that had an KalenderEintrag inline form because those three models do not have a KalenderEintrag field in their model definition and so will not have a KalenderEintrag field in the clean_data dictionary.
Reply all
Reply to author
Forward
0 new messages