[Answer]-Django making recursive calls on relationship

0πŸ‘

βœ…

I may be misunderstanding your question, but I think I have a similar situation. In the dropdown you want the object to be labelled with the name of the location. If there is a parent for that location, you would like to show the name of that parent as well within parentheses following the location name.

You can accomplish this by overriding the __init__ method of your ModelForm:

def __init__(self, *args, **kwargs):
    def new_label_from_instance(self, obj):
        try:
            #see if there is a parent or not
            p = obj.parent 
        except:   
            #no parent; use the location's default label
            rep = obj.description
            return rep
        #if we find a location's parent, p=parent label and d=location label
        d = obj.description
        rep = "%s (%s)" % (d, p)
        return rep

    super(PublisherCreateTSCForm, self).__init__(*args, **kwargs)
    funcType = type(self.fields['location'].label_from_instance)
    self.fields['location'].label_from_instance = funcType(new_label_from_instance, self.fields['location'], forms.models.ChoiceField)

You should know the consequences of doing this before you do it. Check out this old question:

Django CheckboxSelectMultiple override 'choices' from ModelForm

And the docs related to label_from_instance here (bottom of the linked section): https://docs.djangoproject.com/en/1.7/ref/forms/fields/#modelchoicefield

πŸ‘€souldeux

1πŸ‘

Finally I did this:

In the forms.py I created a method:

def get_locations_with_parents():
    location_list = [(0,'Select One ...')]
    locations = Position.objects.raw('select l.id, l.name, p.name as parent from locations l left join locations p on l.parent_id = p.id order by parent, l.name')
    for l in locations:
        if l.parent:
            location = (int(l.id), l.name + " (" + l.parent + ")")
        else:
            location = (int(l.id), l.name)

        location_list.append(location)

    return tuple(location_list)

and then in the form I use
locations = forms.ChoiceField(choices=get_locations_with_parents(), validators=[validate_empty])

It does the trick and it doesn’t do 2000 queries to the DB anymore. There are some validators and clean and so… but does not really relevant to the solution.

πŸ‘€Fabiot

Leave a comment