Chris Lamb

Readline tab completion using Django models

The following snippet allows readline-style tab completion backed onto Django models. I am using this in management commands in preference to specifying primary keys as arguments.

class QuerySetCompleter(object):
    def __init__(self, qs, field):
        self.qs = qs
        self.field = field
        self.prefix = None

    def __call__(self, prefix, index):
        if prefix != self.prefix:
            qs = self.qs.values_list(self.field, flat=True)

            if prefix:
                qs = qs.filter(**{
                    '%s__startswith' % self.field: prefix,
                })

            self.matching = list(qs)
            self.prefix = prefix

        try:
            return self.matching[index]
        except IndexError:
            return None

Example usage:

import readline

from mymodels import MyModel

completer = QuerySetCompleter(MyModel.objects.all(), 'name')
readline.set_completer(completer)

readline.parse_and_bind("tab: complete")
readline.set_completer_delims('')

while 1:
    print repr(raw_input(">>> "))

Pressing <tab> at this >>> prompt will complete from the name field of the MyModel model just like a regular shell would.

We call readline.set_completer_delims as our items may contain word delimeters - otherwise readline would attempt a seperate completion of (eg) "Bar" if one of our items was "Foo Bar".


Chris Lamb is a freelance Django developer and Debian developer. You can read other posts by me, see software I have written or read more about me. You can also follow me @lolamby.


Tags: Hacks Django GNU/Linux

Planets: WUGLUG UWCS Debian ALUG

Sunday 27th December 2009