def anti_loop(field_data, all_data):
"""
Make sure we don't create an infinite loop with a
self-referencing foreign key.
Assumes a required, unique slug field ('slug') and an optional
self-referencing foreign key ('parent'). All_data doesn't give
you the object's ID, so we will find it via the unique slug.
If either is not present we pass -- if there's no parent chosen
it's not a problem, and if there is no slug present the
submission will fail on that validation instead. It is worth
noting that if the user changes the slug field on submission AND
picks a bad parent it will not be caught.
Infinite loop cases:
1. A references A
2. A tries to reference B, which is currently referencing A
"""
parent = all_data.get('parent', '')
slug = all_data.get('slug', '')
error_msg = u"Please chose a parent that does not result in an infinite loop!"
if parent and slug:
try:
this_category = Category.objects.get(slug = slug)
parent_category = Category.objects.get(pk = int(parent))
if parent_category.id == this_category.id or parent_category.parent == this_category:
raise ValidationError(error_msg)
except ObjectDoesNotExist:
pass
Comments
I've written a workaround that addresses the problem of not having the ID of the object being edited. It takes a bit of code to make it happen, but it's been working very well for my projects. Check it out in my article.
Mike Kibbel, Web Developer, Capstrat
#