ivelum/djangoql

Does search in DjangoQLField.get_options() work?

Closed this issue · 8 comments

I know that in the changelog it says that search in get_options() is 'breaking' in version 0.14.0, but does it now work in version 0.14.1?

I am asking because, after updating to 0.14.1, if I change one of my fields from this code

class SearchFieldOptUsername(StrField):
    """Create a list of unique users' usernames for search"""

    model = User
    name = 'username'
    suggest_options = True
    id_list = []

    def get_options(self):

        return super(SearchFieldOptUsername, self).get_options().\
        filter(id__in=self.id_list).\
        order_by(self.name).\
        values_list(self.name, flat=True)

to this code

class SearchFieldOptUsername(StrField):
    """Create a list of unique users' usernames for search"""

    model = User
    name = 'username'
    suggest_options = True
    id_list = []

    def get_options(self, search):

        return self.model.\
        filter(id__in=self.id_list).\
        filter(username__icontains=search).\
        order_by(self.name).\
        values_list(self.name, flat=True)

I stop getting suggestions.

Thanks!

@stebunovd sorry I accidentally saved the new issue before writing out what the issue is :)

yeah, I see. There were no changes to get_options() behavior in v0.14.1 - it was just a minor unrelated bugfix. In the code sample above, suggestion options are generated by your custom code, so if you don't see anything, that means that your get_options() method doesn't return anything. I'd recommend debugging this issue by checking the query in this method. For example, it mentions filter(id__in=self.id_list) but the id_list defined above is empty - could it be the issue?

Right, I do overwrite id_list upon inheriting SearchFieldOptUsername into other classes, and even if it was indeed empty for whatever reason, then I default to all records. Above I just thought to keep things nice and simple. This is the actual full method (there are more users than "AnonymousUser", "guest", "admin" in my db :))

class SearchFieldOptUsername(StrField):
    """Create a list of unique users' usernames for search"""

    model = User
    name = 'username'
    suggest_options = True
    id_list = []

    def get_options(self, search):
        """Removes admin, guest and anaonymous accounts from 
        the list of options, distinct() returns only unique values
        sorted in alphabetical order"""

        # from https://stackoverflow.com/questions/14907525/how-can-i-chain-djangos-in-and-iexact-queryset-field-lookups/14908214#14908214
        excluded_users = ["AnonymousUser", "guest", "admin"]
        q_list = map(lambda n: Q(username__iexact=n), excluded_users)
        q_list = reduce(lambda a, b: a | b, q_list)

        if self.id_list:
            return self.model.\
            filter(id__in=self.id_list).\
            filter(username__icontains=search).\
            exclude(q_list).\
            order_by(self.name).\
            values_list(self.name, flat=True)
        else:
            return self.model.\
            filter(username__icontains=search).\
            exclude(q_list).\
            distinct().order_by(self.name).\
            values_list(self.name, flat=True)

does the query return anything?

First of all, I realized that there was a mistake in the code above, I forgot to include objects, after some changes. Anyhow, the correct code should be

class SearchFieldOptUsername(StrField):
    """Create a list of unique users' usernames for search"""

    model = User
    name = 'username'
    suggest_options = True
    id_list = []

    def get_options(self, search):
        """exclude(id__in=[1,20,36]) removes admin, guest and anaonymous accounts from 
        the list of options, distinct() returns only unique values
        sorted in alphabetical order"""

        # from https://stackoverflow.com/questions/14907525/how-can-i-chain-djangos-in-and-iexact-queryset-field-lookups/14908214#14908214
        excluded_users = ["AnonymousUser","guest","admin"]
        q_list = map(lambda n: Q(username__iexact=n), excluded_users)
        q_list = reduce(lambda a, b: a | b, q_list)

        if self.id_list:
            return self.model.objects.\
            filter(id__in=self.id_list).\
            filter(username__icontains=search).\
            exclude(q_list).\
            order_by(self.name).\
            values_list(self.name, flat=True)
        else:
            return self.model.objects.\
            filter(username__icontains=search).\
            exclude(q_list).\
            distinct().order_by(self.name).\
            values_list(self.name, flat=True)

But even after fixing that it doesn't work. If I run the following, in the Django shell, I get

>>> from collection_management.admin import SearchFieldOptUsername
>>> o = SearchFieldOptUsername()
>>> o.get_options('nic')
<QuerySet ['niczilio']>

as expected. But when I try that query in the admin, I don't get any options.

Ah, problem solved, I had to run collectstatic to update the .js file from djangoql. Face palm!

cool, I'm glad you figured it out