Pegase745 / sqlalchemy-datatables

SQLAlchemy integration of jQuery DataTables >= 1.10.x (Pyramid and Flask examples)
MIT License
159 stars 67 forks source link

columns using object methods #97

Closed lhayhurst closed 7 years ago

lhayhurst commented 7 years ago

Hi, nice library, thank you! From the examples, I see that the columns can be defined either using a reference to the model attribute or a function; is it possible to define the column as a reference to an object method? IE:

columns = [ ColumnDT(User.name), #model attribute
                    func.strftime('%d-%m-%Y', User.birthday), #function 
                    user.get_edit_url() ] #method call on instance of user class

In this case, the third column is a url to the user's edit functionality, constructed on the fly.

Cheers

tdamsma commented 7 years ago

Internally a query is constructed and passed to the output without considering the python object mapping. So if the get_edit_url method is python only, it will not work. It does work with column_properties, and I expect also with hybrid_properties. Implement something like user.edit_url = column_property() and you'll be fine.

Alternatively, just construct the url in the query with simple string concatenation:

edit_url = request.url('edit_user')
columns = [ ColumnDT(User.name), #model attribute
                ColumnDT(edit_url + '/' + User.id)] 

Even more advanced, and provided the edit url follows a simple form like http://localhost/users/{user_name}/edit, it can suffice to just pass the user name to the data table, and then use some js to upgrade the user name in the table to a hyperlink to the edit page.

Here is an example I use for this:

        columns = [
            ColumnDT(User.name),
            ColumnDT(User.email),
            ColumnDT(User.name.label('Update user')
        ]

        # some js to generate links to user update view
        datatable_opts = """
            "columnDefs" : [
                {
                    "render": function (data, type, row) {
                        return '<a href="%s">update</a>'
                            .replace('NAME', data);
                    },
                    "targets": %s
                }
                }
            ]
        """ % (
            self.request.route_url('user_edit',
                                   _query={'user_name': 'NAME'}))

        query = session.query().\
            select_from(User)

        return QueryView(request, query=query, datatable_opts=datatable_opts,
                         columns=columns, name=name, view=self)
lhayhurst commented 7 years ago

Thanks for the great reply, gets me started! Out of curiosity, for the snippet provided above, what self variable is in scope? Cheers!

lhayhurst commented 7 years ago

Sorry to re-open! This QueryView class you reference above, is it one of your own? Sadly it doesn't work with hybrid properties :-(

tdamsma commented 7 years ago

indeed the QueryView is my own. The example came from a project where I use the pattern where all views are classmethods, so they can share certain properties (like the menu). I copied this pattern from the deform2 demo site.

For hybrid views, be sure to implement the expression. Also, most hybrid_properties (if they are read only at east) can be better implemented as column_properties