Login

Self-referencing Foreign Key Infinite Loop

Author:
minarets
Posted:
September 17, 2007
Language:
Python
Version:
.96
Tags:
validator foreignkey
Score:
2 (after 2 ratings)

Make sure we don't create an infinite loop with a self-referencing foreign key.

Many times I have needed category models that reference themselves, providing a flexible way to make children categories, grandchildren categories, etc. If you chain the slugs (or even ids) there's a chance you could end up with an infinite loop.

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
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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

More like this

  1. Command to dump data as a python script by willhardy 6 years, 10 months ago
  2. Hierarchical page slugs by baumer1122 7 years, 8 months ago
  3. self-related objects list with links by kumbry 7 years, 5 months ago
  4. dumpdata/loaddata with MySQL and ForeignKeys by cmgreen 7 years, 3 months ago
  5. Accessing URL variable from within a Form by blacktav 1 year, 7 months ago

Comments

Please login first before commenting.