Opened 12 years ago

Closed 3 years ago

#19721 closed New feature (fixed)

Django admin allows filtering using the field lookups such as "in", but it is impossible to include a value that contains a comma

Reported by: aruseni Owned by: Shreya Bamne
Component: contrib.admin Version: 1.4
Severity: Normal Keywords:
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The admin site allows you to filter the queryset in the changelist in a plenty of different ways. Notably, it allows you to filter the records by multiple values (if the field's value is one of the specified value options, then such record is considered matching).

For example, you can test it with a query string like this:

/admin/auth/user/?username__in=johnny,viola,gordon

Unfortunately, there is a big limitation at the moment: you can't include a value option that contains a comma (or a few).

The function that splits the string is prepare_lookup_value, found in contrib.admin.util.

Attachments (1)

comma_in__in_data.patch (2.8 KB ) - added by chlunde 12 years ago.
Patch with test

Download all attachments as: .zip

Change History (17)

comment:1 by aruseni, 12 years ago

Right now, the following workaround (besides monkey patching prepare_lookup_value) works for me:

def multiple_value_options_filter_factory(field_name):
    """
    This is a class factory. It creates classes used
    for filtering by multiple value options.

    The field options are separated by a "|" character.

    If any of the specified options (or "") is the
    value of the field of a record, then such record
    is considered matching.

    The name of the field that should be using for
    filtering is passed as the argument to the function.
    """
    class MultipleValueOptionsFilter(admin.ListFilter):
        # Human-readable title which will be displayed in the
        # right admin sidebar just above the filter options.
        title = field_name

        # Parameter for the filter that will be used in the URL query.
        parameter_name = "_".join([field_name, "in"])

        def __init__(self, request, params, model, model_admin):
            self.used_parameters = {}
            for p in self.expected_parameters():
                if p in params:
                    value = params.pop(p)
                    self.used_parameters[p] = value.split("|")

        def expected_parameters(self):
            return [self.parameter_name]

        def has_output(self):
            return True

        def choices(self, cl):
            yield {
                'selected': False,
                'query_string': cl.get_query_string({}, [self.parameter_name]),
                'display': 'All',
            }

        def queryset(self, request, queryset):
            """
            Returns the filtered queryset based on the value
            provided in the query string and retrievable via
            `self.value()`.
            """
            value_options = self.used_parameters.get(self.parameter_name, None)
            if not value_options:
                return queryset
            filter_dict = {"__".join([field_name, "in"]): value_options}
            return queryset.filter(**filter_dict)

    return MultipleValueOptionsFilter

I put it in list_filter of the ModelAdmin class:

list_filter = (
    multiple_value_options_filter_factory("some_model_field_to_filter"),
    multiple_value_options_filter_factory("some_other_model_field"),
)

And then including value options that contain commas becomes possible:

?some_model_field_to_filter_in=Look at this, it works now|Yeah, definitely

by chlunde, 12 years ago

Attachment: comma_in__in_data.patch added

Patch with test

comment:2 by anonymous, 12 years ago

Has patch: set

Not sure if it's a good idea... I've attached a patch which allows you to escape comma and backslash.

It will break any existing code searching for multiple backslashes (most likely not an issue).

comment:3 by Carl Meyer, 12 years ago

Triage Stage: UnreviewedAccepted

Not sure if the backslash-escape is a good idea, or if we just need to provide a way to easily subclass the standard ListFilter and replace just the separator character (and then document that). Either way, it should be easier to filter on values including a comma.

comment:4 by Aymeric Augustin, 12 years ago

Type: UncategorizedBug

comment:5 by Tim Graham, 11 years ago

Patch needs improvement: set

Patch no longer applies cleanly.

comment:6 by Chris Beaven, 10 years ago

An interesting way to solve this would be to use getlist() when pulling the filter arguments without an explicit filter lookup and if a list is found, use __in rather than __exact.

So to match the example given in the description, you'd be able to do:
/admin/auth/user/?username=johnny&username=viola,with,comma

comment:7 by Shreya Bamne, 3 years ago

Owner: changed from nobody to Shreya Bamne
Status: newassigned

Since this is a older ticket, I tried writing a small test in tests\admin_filters\tests.py to confirm the issue and I was able to do so. I have started working on this ticket and assigning the ticket to me.

comment:8 by Jacob Walls, 3 years ago

Patch needs improvement: unset

comment:9 by Shreya Bamne, 3 years ago

I am not sure if this is the right place to ask this, but I was wondering how long should I wait for my PR to get reviewed? I am new to the Django community, any help is appreciated. Thank you.

in reply to:  9 comment:10 by Mariusz Felisiak, 3 years ago

Replying to Shreya Bamne:

I am not sure if this is the right place to ask this, but I was wondering how long should I wait for my PR to get reviewed? I am new to the Django community, any help is appreciated. Thank you.

Unfortunately, you have to be patient. We try our best, but usually you have to wait a few weeks. Thanks for preparing a patch! See also FAQ: Contributing code.

comment:11 by Shreya Bamne, 3 years ago

Thank you Mariusz! I'll keep checking the PR every week.

comment:12 by Carlton Gibson, 3 years ago

Needs documentation: set
Patch needs improvement: set
Type: BugNew feature

comment:13 by Carlton Gibson <carlton@…>, 3 years ago

In e53aea2e:

Refs #19721 -- Moved ModelAdmin.list_filter docs into a separate file.

Co-authored-by: Carlton Gibson <carlton.gibson@…>

comment:14 by Carlton Gibson, 3 years ago

Needs documentation: unset
Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

comment:15 by Carlton Gibson <carlton.gibson@…>, 3 years ago

In 2b76f457:

Refs #19721 -- Corrected list formatting in admin filters docs.

comment:16 by Carlton Gibson <carlton.gibson@…>, 3 years ago

Resolution: fixed
Status: assignedclosed

In 8a4e5067:

Fixed #19721 -- Allowed admin filters to customize the list separator.

Note: See TracTickets for help on using tickets.
Back to Top