I am trying to implement my own validation for a many-to-many relation (m2m) since django does not allow m2m fields in the unique-together
constraint (https://code.djangoproject.com/ticket/702) (Django Unique Together (with foreign keys))
What I want is to check is if a newly created object instance is already existent within the scope of a m2m related model.
Imagine I have the following 3 models:
class Juice(model.Model)
name=CharField,
year=IntegerField,
flavor=CharField
class Company(model.Model)
name=CharField,
cooperates=ManytoManyField
juice=ManytoManyFiedl
class Cooperate(model.Model)
name=CharField
That means that a company can have many juices and many juices can belong to many companies. Equally a company can belong to many cooperates and a cooperate can belong to many companies.
What I want to implement now is the following restriction: Whenever I create a new juice with name
, year
and flavor
it should validate if a juice like this already exists within the scope of the Cooperate model. That means if there is any company within the cooperates that already have this juice it should raise a ValidationError
. Let's say for example I create a new juice (bb-sparkle, 2020, blueberry) it should raise a validation if cooperate-optimusprime
already has a company (e.g. company-truck-juices
) that has a juice with bb-sparkle
, 2020
, blueberry
. But it should not raise an error when I create the same juice (bb-sparkle, 2020, blueberry) for the cooperate coorperate-megatron
that has a company (e.g. company-airplane-juices
).
What I am trying to do is to overwrite the validation method before saving an object:
def validate_unique(self, exclude=None):
"""Overwrite validation to check for uniqueness within cooperate scope."""
juice = Juice.objects.filter(
year=self.year,
name=self.name,
flavor=self.flavor,
)
for j in juice:
for company in j.company_set.all():
for cooperate in company.cooperates.all():
if cooperate is not None:
print(cooperate)
raise ValidationError(
'Juice instances must be unique within cooperate scope.'
)
def save(self, *args, **kwargs):
"""Overwrite save to call validation before saving."""
self.validate_unique()
super(Juice, self).save(*args, **kwargs)
This does not work since I am only checking if the cooperate is not None. But I don't really know how I can filter this correctly because I only have access to the parameters in the self
-object.
Any help is much appreciated. Thanks in advance!