librelist archives

« back to archive

implementing list with sort/filter

implementing list with sort/filter

From:
Sebastien Estienne
Date:
2010-04-26 @ 21:57
Hello,

I'd like to have an advice about  a classic pattern.

I have a view listing some objects with a pagination.

i'd like to apply filter and sort options on this list, but i don't
know if i should pass these filters using the query string, a session
cookie or the url path as filters and sort options are optionnal and
the order doesn't matter.

thanx,
Sebastien Estienne

Re: [flask] implementing list with sort/filter

From:
Armin Ronacher
Date:
2010-04-26 @ 22:04
Hi,

On 4/26/10 11:57 PM, Sebastien Estienne wrote:
> i'd like to apply filter and sort options on this list, but i don't
> know if i should pass these filters using the query string, a session
> cookie or the url path as filters and sort options are optionnal and
> the order doesn't matter.
It should be encoded as part of the URL.  That way it can be bookmarked 
and makes caching easier.

I usually put the page into the URL, like this:

    @app.route('/list/', defaults={'page': 1})
    @app.route('/list/page/<int:page>')
    def my_list(page):
        pass

When however that list also requires re-ordering query strings often 
make it easier.  For me I decide to start using query strings when any 
argument might be optional or if a form is used to generate the URLs to 
the page (like in a bug tracker where you can filter by open/closed 
tickets, tickets by owner etc.).  There the filtering can be extended 
and simplified all the time.


Regards,
Armin

Re: [flask] implementing list with sort/filter

From:
Sebastien Estienne
Date:
2010-04-26 @ 22:17
> It should be encoded as part of the URL.  That way it can be bookmarked
> and makes caching easier.

As it's a backoffice, bookmarking is not a requirement so i
implemented pagination with the query string ?page=1

I didn't know that it was possible to use this app.route syntax with 2
decorators for default values:
>    @app.route('/list/', defaults={'page': 1})
>    @app.route('/list/page/<int:page>')
>    def my_list(page):
>        pass
>
> When however that list also requires re-ordering query strings often
> make it easier.  For me I decide to start using query strings when any
> argument might be optional or if a form is used to generate the URLs to
> the page (like in a bug tracker where you can filter by open/closed
> tickets, tickets by owner etc.).  There the filtering can be extended
> and simplified all the time.

I never really understood why the query string is handled in a
different manner than the url path.
I think that it would be convenient if some parameters of the view
could be set like they are from the url path and not requiring to
access them throught request.attrs.get()
For example i don't see any easy way to use url_for() with query
strings, maybe url_for , could have a dict parameter being the query
thing eg:

url_for('task_list', page=1, qs={'status' : 'ready', 'sort' : 'date'})
->
/task/list/page/1?status=ready&sort=date

so i could pass this dict to the view and do things like this:
{% for status in ['ready', 'error', 'pending'] %}
<a href={{ url_for('task_list', page=1, qs={'status' : status, 'sort'
: 'date'}) }}>{{status}}</a>
{% endfor %}

Re: [flask] implementing list with sort/filter

From:
Armin Ronacher
Date:
2010-04-26 @ 23:19
Hi,

On 2010-04-27 12:17 AM, Sebastien Estienne wrote:
> I never really understood why the query string is handled in a
> different manner than the url path.
Combination of the URI/IRI RFCs in combination with how CGI works :) 
Also a weird clause in the HTTP RFC regarding caching comes into play there.

> For example i don't see any easy way to use url_for() with query
> strings, maybe url_for , could have a dict parameter being the query
> thing eg:
Unknown parameters are automatically appended as query string::

     @app.route('/')
     def index():
         pass

     url_for('index', page=1) --> '/?page=1'


Regards,
Armin

Re: [flask] implementing list with sort/filter

From:
Sebastien Estienne
Date:
2010-04-26 @ 23:38
> Combination of the URI/IRI RFCs in combination with how CGI works :)
> Also a weird clause in the HTTP RFC regarding caching comes into play there.
Yes, i undestand these technical reasons, from a 'framework user' point of view.
It might seem handy that things work like this:
@app.route('/list/page/<int:page>')
 def my_list(page, sort=None, status=None):

with url:
/list/page/1?sort=date&status=ready

I'm sure there is a good reason not to do this :)

>> For example i don't see any easy way to use url_for() with query
>> strings, maybe url_for , could have a dict parameter being the query
>> thing eg:
> Unknown parameters are automatically appended as query string::
>
>     @app.route('/')
>     def index():
>         pass
>
>     url_for('index', page=1) --> '/?page=1'
Ah this is exactly what i need, maybe the doc of url_for should say
more about this nice behaviour.

Armin, thanx for your help!