Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
900 views
in Technique[技术] by (71.8m points)

python - Django: how to validate m2m relationships?

Let's say I have a Basket model and I want to validate that no more than 5 Items can be added to it:

class Basket(models.Model):
    items = models.ManyToManyField('Item')

    def save(self, *args, **kwargs):
        self.full_clean()
        super(Basket, self).save(*args, **kwargs)

    def clean(self):
        super(Basket, self).clean()
        if self.items.count() > 5:
            raise ValidationError('This basket can't have so many items')

But when trying to save a Basket a RuntimeError is thrown because the maximum recursion depth is exceeded.

The error is the following:

ValueError: "<Basket: Basket>" needs to have a value for field "basket" before this many-to-many relationship can be used.

It happens in the if self.items.count() > 5: line.

Apparently Django's intricacies simply won't allow you to validate m2m relationships when saving a model. How can I validate them then?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can never validate relationships in the clean method of the model. This is because at clean time, the model may not yet exist, as is the case with your Basket. Something that does not exist, can also not have relationships.

You either need to do your validation on the form data as pointed out by @bhattravii, or call form.save(commit=False) and implement a method called save_m2m, which implements the limit.

To enforce the limit at the model level, you need to listen to the m2m_changed signal. Note that providing feedback to the end user is a lot harder, but it does prevent overfilling the basket through different means.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...