justpy-org / justpy

An object oriented high-level Python Web Framework that requires no frontend programming
https://justpy.io
Apache License 2.0
1.22k stars 96 forks source link

Combining Quasar and ag-Grid for CRUD? #50

Closed hardreddata closed 4 years ago

hardreddata commented 4 years ago

I discovered this library today and have been enjoying the ag-Grid examples.

One can use pandas with SQL queries and in turn use JustPy to show these dataframes as tables. This is hugely useful given the small amount of code required and my programming abilities.

I note that I can grid.options.columnDefs[1].editable = True (here for column 1) to allow the table rows to be edited in place. Is it possible to pass these updates back into the dataframe?

More generally I am in need of a CRUD application which can allow end users to edit various database tables.

I thought perhaps the QButtons example could be modified such that each button represented a DB table but I am unsure if Quasar and ag-Grid can be combined in such a way. As best I can tell ag-Grid is focussed on presenting a single table. Perhaps QTabs where each tab reflects a DB table? I note you mention QTabPanels is not working.

Any advice on how to approach this with JustPy would be very welcome.

Many thanks.

elimintz commented 4 years ago

Could you please take a look at https://justpy.io/grids_tutorial/database/ ? Please let me know what you would like to see in addition to that example.

knoxvilledatabase commented 4 years ago

Not sure if you are wanting inline editing or a button click event. For a button click event this is what we had to do. Basically on cell click it prints the column id assuming there is an ID column:

  grid = jp.AgGrid(a=whatever)   grid.on('cellClicked', cell_click)   def cell_click(self, target, msg):         if msg['colId'] == 'Some Text':             if msg['data'].get('Some Text', '') != '':                 print(msg['data']['ID'])                 print(msg['data']['Some Text'])

Hope this helps, and if you come up with a better way I would be interested in seeing it.

Credit for this goes to: https://github.com/johnrtipton

hardreddata commented 4 years ago

Hi @elimintz @knoxvilledatabase

Thanks for the prompt responses. I did miss the the SQLite Chinook example on my first pass. I see now this includes multiple tables and some Quasar. This is really great.

If we modify the example slightly to make the grid inline editable

def value_change(self, msg):
    # print(self)
    # print(msg)
    # # Perhaps this?
    # self.['rowData'].iloc[msg.rowIndex] = msg.['data'].values

def db_test(request):
    wp = jp.QuasarPage()
    table_name = request.query_params.get('table', 'albums')
    s = jp.QSelect(options=table_names, a=wp, label="Select Table", outlined=True, input=selected_event,
                   style='width: 350px; margin: 0.25rem; padding: 0.25rem;', value=table_name)
    g = tables[table_name].jp.ag_grid(a=wp, style='height: 90vh; width: 99%; margin: 0.25rem; padding: 0.25rem;')
    g.options.pagination = True
    g.options.paginationAutoPageSize = True
    g.on('cellValueChanged', value_change)
    # make grid editable
    for z in range(len(tables[table_name].columns)):
        g.options.columnDefs[z].editable = True
    wp.g = g
    return wp

Is there a nice way to push the edits back into the tables dataframe? Or indeed add/remove rows?

On the example I altered selected_event adding a similar msg.page.g.options.columnDefs[z].editable = True

If this is too much work I understand if you choose not to respond.

Maybe my half day with JustPy has made me lazy as https://medium.com/ag-grid/building-a-crud-application-with-ag-grid-part-4-3189034df922 sure looks complicated in comparison.

I think I can probably use https://stackoverflow.com/questions/52188446/pandas-to-sql-to-update-unique-values-in-db or similar from there as replacing the whole table doesn't seem wise. I am more comfortable with SQL than Python.

Any insight is appreciated.

knoxvilledatabase commented 4 years ago

If you're familiar with Django, one option is to use the django orm with justpy:

sys.path.append('../path_to_project') os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') from django import setup setup()

Import your django models: from my_django_project.models import MyModel

Then you can interact with the django orm from the grid:

records = MyModel.objects.filter(is_active=True).order_by('id')

grid_data = [     {         'ID': record.id,         'First Name': record.first_name,     }     for record in records ]

dj_df = pandas.DataFrame(grid_data) grid.load_pandas_frame(dj_df)

elimintz commented 4 years ago

Below please find a simple example in which you use the grid's cellValueChanged event to capture changes from edit. In the example below when a cell changes the event handler cell_changed is called. In the example the values in msg are printed but that is the place where you would update the server side data repository. Let me know if this is what you are looking for.

I will work on a more complete CRUD example.

import justpy as jp

grid_options = """
{
    defaultColDef: {
        filter: true,
        sortable: true,
        resizable: true,
        cellStyle: {textAlign: 'center'},
        headerClass: 'font-bold'
    }, 
      columnDefs: [
      {headerName: "Make", field: "make"},
      {headerName: "Model", field: "model"},
      {headerName: "Price", field: "price"}
    ],
      rowData: [
      {make: "Toyota", model: "Celica", price: 35000},
      {make: "Ford", model: "Mondeo", price: 32000},
      {make: "Porsche", model: "Boxter", price: 72000}
    ]
}
"""

def cell_changed(self, msg):
    print(msg)
    print(f'Old value: {msg.oldValue}, New value: {msg.newValue}, Row Index: {msg.rowIndex}, Column ID: {msg.colId}')
    print(f'Row data: {msg.data}')
    # Here you would update your database or Pandas frame etc.

def grid_test():
    wp = jp.WebPage()
    grid = jp.AgGrid(a=wp, options=grid_options, style='height: 200px; width: 300px; margin: 0.25em')
    for col_def in grid.options.columnDefs:
        col_def.editable = True  # You can add this directly to the columnDefs in grid_options
    grid.on('cellValueChanged', cell_changed)
    return wp

jp.justpy(grid_test)
hardreddata commented 4 years ago

This is helpful.

Thanks for the assistance.

You may have gathered I don't consider myself much of a developer, and more of an all-rounder. Your paragraph Hopefully, JustPy will enable teaching web development in introductory Python courses by reducing the complexity of web development. makes real sense to me.

WolfgangFahl commented 2 years ago

issue50