Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to perform validation when using add() on many to many relation ships in Django?

i have a Category model with parent/child self relation For primary category and sub categories :

class Place(models.Model):
    name = models.CharField(_("name"), max_length=100)
    categories = models.ManyToManyField("Category", verbose_name=_("categories"))

class Category(models.Model):
    name = models.CharField(_("name"), max_length=100)
    parent = models.ForeignKey('self', blank=True, null=True, related_name='child_set')

i need to prevent orphans, to prevent this kind of errors (in admin web interface)

c_parent = Category(name='Restaurant')
c_parent.save()

c_child = Category(name="Japanese restaurant", parent=c_parent)
c_child.save()

place1 = Place (name="Planet sushi")
place1.save()
place1.categories.add(c_parent)
place1.categories.add(c_child)

So now we have a new Place called "Planet sushi", it's a Restaurant (root category), and a Japanese Restaurant (sub category)

but i want to prevent this kind of things :

place2 = Place (name="Tokyofood")
place2.save()

place2.categories.add(c_child)

because parent is not set, or is not the correct parent category

where can i do form validation for the admin ? and other forms (because any user can add a new place and will have to choose correct categories for)

like image 383
Julien Avatar asked Feb 04 '10 15:02

Julien


People also ask

How does Django handle many-to-many relationship?

Behind the scenes, Django creates an intermediary join table to represent the many-to-many relationship. By default, this table name is generated using the name of the many-to-many field and the name of the table for the model that contains it.

How take data from many-to-many field in Django?

A ManyToManyField in Django is a field that allows multiple objects to be stored. This is useful and applicable for things such as shopping carts, where a user can buy multiple products. To add an item to a ManyToManyField, we can use the add() function.

What is validator in Django?

A validator is a callable that takes a value and raises a ValidationError if it doesn't meet some criteria. Validators can be useful for reusing validation logic between different types of fields.

How models work in Django?

Django web applications access and manage data through Python objects referred to as models. Models define the structure of stored data, including the field types and possibly also their maximum size, default values, selection list options, help text for documentation, label text for forms, etc.


1 Answers

Use signals and more specifically the m2m_changed signal.

Take time to read the doc as signals are not easy to get, and the m2m_changed is the most complicated as it's one signal for everything that appends to the m2m relationship.

Basically what you want to check if action is pre_add, then raise a ValidationError if the category parent doesn't match your requirements.

Take some time on checking what is sender and instance, espacially since it changes according to the value of reverse.

like image 76
e-satis Avatar answered Nov 01 '22 13:11

e-satis