1

Validation on this object

I am trying to write some validations on form input and need to check that the instance being created doesn't already exist under the same grandparent. The field I am validating against isn't a primary key as it can exist outside the 'family'. I can't seem to think of an appropriate query for this but so far I have the following which works:

existing_parents = Parent.objects.filter(grandparent=active_parent.grandparent)
for parent in existing_parents:
    existing_children = parent.children.all()
            for children in existing_children
                if existing_children.identifier == identifier:
                    self._errors["form_field"] = self.error_class(
                        ["That child already exists"]
                    )
                else: 
                    pass

Just wondered if there was a lookup I can do that simplifies it?

fdeboo
  • 325
  • 1
  • 11

1 Answers1

1

Yes, you can check this with:

Child.objects.filter(
    identifier=identifier,
    parent__grandparent__parents=active_parent
).exists()

We here thus start from the Child model, move up to the grandparent (with parent__grandparent and then move down with __parents, and check if such identifier already exists). Here parents is the value for the related_query_name=… [Django-doc] of the ForeignKeys from Parent to GrandParent, and from Child to Parent. If you did not specify a related_query_name=… parameter, it will use the related_name=… [Django-doc] for that name, and if you did not specify that either, then it uses the name of the model in lowercase.

This will of course check all grandchildren, including the one you want to edit and already exists in the database. You thus can exclude a Child that aready exists with:

Child.objects.exclude(
    pk=pk_of_child_to_exclude
).filter(
    identifier=identifier,
    parent__grandparent__parents=active_parent
).exists()
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • Thank you! Trying to put this into practice but it seems to call the error whenever it finds an instance with the matching identifier, even if from another gradnparent object (which I don't want). Maybe I should post the models.. – fdeboo Dec 20 '20 at 13:34
  • @fdeboo: are you sure it is not simply the same child like the one you aim to update? Note that the children can be of the *same* parent. So they can be the same child, a sibling, or a cousin. – Willem Van Onsem Dec 20 '20 at 13:35
  • 1
    @fdeboo: that is exactly why, if you want to *update* a child, you should exclude the one you are updating at that moment, since otherwise the query is trivially true: the child you aim to update of course has a cousin with the same identifier: himself. – Willem Van Onsem Dec 20 '20 at 13:37
  • I am sure as this is the validation before the child object is saved/created. Let me double check I'm not doing something stupid – fdeboo Dec 20 '20 at 13:45
  • @fdeboo: I think I misunderstood the question. Normally it should be fixed now. – Willem Van Onsem Dec 20 '20 at 13:52
  • Is it not because the Child model refers to all children regardless of grandparent? – fdeboo Dec 20 '20 at 13:53
  • @fdeboo: I made a mistake by not filtering on the `active_parent`, normally with the extra filter, that should be fixed. – Willem Van Onsem Dec 20 '20 at 13:54