plomino / Plomino

Powerful and flexible web-based application builder
33 stars 37 forks source link

Programmatically adding data to Datagrid field #775

Closed AshRaghav closed 7 years ago

AshRaghav commented 7 years ago

Hi @ebrehault ,

I have been trying to add some data to the Datagrid field (not quite successful) though. I have 5 columns in total in the Datagrid. I tried using the below code and the data got stored literally in that format.

val = ["Now(),Now(),'','UpdatedUserDetails',''"] plominoDocument.setItem('user_tasks',val)

Understandable because I used double quotations (") the data got stored literally.

What is the right way to add data to a Datagrid field here? What fields can be stored as part of the Datagrid? because I have a RICHTEXT field which doesn't seem to be storing even when I add some info directly on the Datagrid using the modal form.

Any further direction is appreciated.

Thanks.

sverbois commented 7 years ago

A datagrid field is a list of list. Did you try val =[["Now(),Now(),'','UpdatedUserDetails',''"]] plominoDocument.setItem('user_tasks',val)

AshRaghav commented 7 years ago

@sverbois - thanks, yes I tried that code and it was funny.

Like I mentioned, it stored Now() instead of substituting with today's date.

And yes I understand it is a list of lists, so not sure how the data should be appended on an ongoing basis.

Do you know if there are any examples out there that shows to add stuff to the datagrid?

Thanks

ebrehault commented 7 years ago

Just remove the double quotes. This should work:


val =[[Now(),Now(),'','UpdatedUserDetails','']]
plominoDocument.setItem('user_tasks',val)```
AshRaghav commented 7 years ago

Thanks @ebrehault - manage to sort this finally after sleeping over it for sometime.

To summarise

  1. Using just Now() won't work and I had to use str(Now()) to ensure the data is stored.
  2. Secondly str(Now()) also had some issues when rendering, turns out the date time format in database was different.
  3. Finally, appending a value to datagrid was somewhat tricky where I had to use asList() method in Utils first to make the existing variable and then use append. Using append directly without converting existing information stored as a List resulted in erasing all the existing data because Datagrid is a list of lists as mentioned before.

Not sure if these points have been experienced previously but thought will share my experience :-)

AshRaghav commented 7 years ago

@ebrehault - I have two other questions relating to fields in Datagrid

  1. I have a main selection list outside the Datagrid in which a value is selected and saved by user. Upon saving, I show them a Datagrid which contains another selection list based on the value selected.

I have successfully managed to show the list based on previous selection inside the Datagrid using

SomeDoc = actual_context(context, search="PlominoDocument")

if SomeDoc: return SomeDoc.getItem('SomeLists') else: SomeListsFin = ['Please select...|'] return SomeListsFin

where SomeLists is a list computed and stored when saving the document.

At this point, after I select a value inside the Datagrid and save, the selection list is showing up as empty. I still tried to save the plomino document after entering values in the Datagrid and I got a "Could not adapt" error.

Module zope.tales.tales, line 696, in evaluate URL: file:/opt/Plone-4.3.3/buildout-cache/eggs/Products.CMFPlomino-1.19-py2.7.egg/Products/CMFPlomino/skins/cmfplomino_templates/EditDocument.pt Line 141, Column 16 Expression: <PythonExpr here.editWithForm(form)>

Module Products.PageTemplates.ZRPythonExpr, line 48, in call __traceback_info__: here.editWithForm(form) Module PythonExpr, line 1, in Module Products.CMFPlomino.PlominoDocument, line 591, in editWithForm Module Products.CMFPlomino.PlominoDocument, line 580, in openWithForm Module Products.CMFPlomino, line 167, in newf Module Products.CMFPlomino.PlominoForm, line 679, in displayDocument Module Products.CMFPlomino, line 167, in newf Module Products.CMFPlomino.PlominoField, line 253, in getFieldRender Module Products.CMFPlomino.fields.datagrid, line 298, in getFieldValue Module Products.CMFPlomino.PlominoDocument, line 226, in getRenderedItem Module Products.CMFPlomino, line 167, in newf Module Products.CMFPlomino.PlominoField, line 282, in getFieldRender Module Products.CMFPlomino.fields.selection, line 101, in getSelectionList Module Products.CMFPlomino.exceptions, line 93, in reportError Module Products.CMFPlone.PloneTool, line 753, in addPortalMessage TypeError: ('Could not adapt', {u'FinalTotal': '70', u'Title': 'K/506/7176', u'THours': '10', 'Form': 'ListForm', u'SomeFieldOne': '10', u'SomeFieldTwo': '10', u'Research': '10', u'TotalOne': '30', 'Plomino_Parent_Document': '6c8518ff314242f9b99badaff906fe06', u'SomeFieldThree': '10', u'TotalTwo': '40', u'SomeFieldFour': '10', u'SomeFieldFive': '10'}, )

Any ideas on why this might be happening?

  1. How do I show the values stored in a Datagrid in a view?

@jean - thought this might be of interest to you.

Thanks

ebrehault commented 7 years ago

1: there is an error when rendering an error message, which is bad of course, but basically just try to fix the error in selection field formula.

2: a view will always display one row by document, so if you display your datagrid values, they have to be concatenated, for example like this:

rows = context.getItem('mydatagrid', [])
return '; '.join([', '.join(row) for row in rows])
AshRaghav commented 7 years ago

Thanks @ebrehault

2 - Managed to solve that. Thanks

1 - I haven't pasted the full error message to be honest. The selection field formula doesn't show any error in the form.

This error shows up when I try to save the form with datagrid. The selection field, as explained previously, is shown based on another selection list in the same form.

I am unsure as to why the could not adapt error is thrown when I save the document after adding some information in the datagrid field.

Traceback (innermost last): Module ZPublisher.Publish, line 138, in publish Module ZPublisher.mapply, line 77, in mapply Module ZPublisher.Publish, line 48, in call_object Module Shared.DC.Scripts.Bindings, line 322, in call Module Shared.DC.Scripts.Bindings, line 359, in _bindAndExec Module Products.CMFCore.FSPageTemplate, line 237, in _exec Module Products.CMFCore.FSPageTemplate, line 177, in pt_render Module Products.PageTemplates.PageTemplate, line 79, in pt_render Module zope.pagetemplate.pagetemplate, line 132, in pt_render Module zope.pagetemplate.pagetemplate, line 240, in call Module zope.tal.talinterpreter, line 271, in call Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 888, in do_useMacro Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 533, in do_optTag_tal Module zope.tal.talinterpreter, line 518, in do_optTag Module zope.tal.talinterpreter, line 513, in no_tag Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 954, in do_defineSlot Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 533, in do_optTag_tal Module zope.tal.talinterpreter, line 518, in do_optTag Module zope.tal.talinterpreter, line 513, in no_tag Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 858, in do_defineMacro Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 954, in do_defineSlot Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 533, in do_optTag_tal Module zope.tal.talinterpreter, line 518, in do_optTag Module zope.tal.talinterpreter, line 513, in no_tag Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 946, in do_defineSlot Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 533, in do_optTag_tal Module zope.tal.talinterpreter, line 518, in do_optTag Module zope.tal.talinterpreter, line 513, in no_tag Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 858, in do_defineMacro Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 533, in do_optTag_tal Module zope.tal.talinterpreter, line 518, in do_optTag Module zope.tal.talinterpreter, line 513, in no_tag Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 852, in do_condition Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 533, in do_optTag_tal Module zope.tal.talinterpreter, line 518, in do_optTag Module zope.tal.talinterpreter, line 513, in no_tag Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 533, in do_optTag_tal Module zope.tal.talinterpreter, line 518, in do_optTag Module zope.tal.talinterpreter, line 513, in no_tag Module zope.tal.talinterpreter, line 343, in interpret Module zope.tal.talinterpreter, line 742, in do_insertStructure_tal Module Products.PageTemplates.Expressions, line 218, in evaluateStructure Module zope.tales.tales, line 696, in evaluate

  • URL: file:/opt/Plone-4.3.3/buildout-cache/eggs/Products.CMFPlomino-1.19-py2.7.egg/Products/CMFPlomino/skins/cmfplomino_templates/EditDocument.pt
  • Line 141, Column 16
  • Expression: <PythonExpr here.editWithForm(form)>
  • Names: {'container': <PloneSite at /clients/cms/site>, 'context': <PlominoDocument at /clients/cms/database/plomino_documents/bf1b1a901f5d43ca9b9bcc909fd05dbb>, 'default': <object object at 0x7f92e7578b60>, 'here': <PlominoDocument at /clients/cms/database/plomino_documents/bf1b1a901f5d43ca9b9bcc909fd05dbb>, 'loop': {}, 'nothing': None, 'options': {'args': ()}, 'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0x7f92cfe69d60>, 'request': <HTTPRequest, URL=/database/plomino_documents/bf1b1a901f5d43ca9b9bcc909fd05dbb/EditDocument>, 'root': , 'template': <FSPageTemplate at /clients/cms/site/EditDocument used for /clients/cms/site/database/plomino_documents/bf1b1a901f5d43ca9b9bcc909fd05dbb>, 'traverse_subpath': [], 'user': <PloneUser 'auser'>} Module Products.PageTemplates.ZRPythonExpr, line 48, in call
  • __traceback_info__: here.editWithForm(form) Module PythonExpr, line 1, in Module Products.CMFPlomino.PlominoDocument, line 591, in editWithForm Module Products.CMFPlomino.PlominoDocument, line 580, in openWithForm Module Products.CMFPlomino, line 167, in newf Module Products.CMFPlomino.PlominoForm, line 679, in displayDocument Module Products.CMFPlomino, line 167, in newf Module Products.CMFPlomino.PlominoField, line 253, in getFieldRender Module Products.CMFPlomino.fields.datagrid, line 298, in getFieldValue Module Products.CMFPlomino.PlominoDocument, line 226, in getRenderedItem Module Products.CMFPlomino, line 167, in newf Module Products.CMFPlomino.PlominoField, line 282, in getFieldRender Module Products.CMFPlomino.fields.selection, line 101, in getSelectionList Module Products.CMFPlomino.exceptions, line 93, in reportError Module Products.CMFPlone.PloneTool, line 753, in addPortalMessage TypeError: ('Could not adapt', {u'FinalTotal': '70', u'Title': 'H/502/0132', u'THours': '10', 'Form': 'ListForm', u'SomeFieldOne': '10', u'SomeFieldTwo': '10', u'Research': '10', u'TotalOne': '30', u'TotalTQT': '70', 'Plomino_Parent_Document': 'bf1b1a901f5d43ca9b9bcc909fd05dbb',, u'SomeFieldThree': '10', u'TotalTwo': '40', u'SomeFieldFour': '10', u'SomeFieldFive': '10'}, InterfaceClass Products.statusmessages.interfaces.IStatusMessage)
ebrehault commented 7 years ago

The "could not adapt" message is a Plomino internal error when trying to render the original error message. The consequence is you cannot see your actual error. But maybe you can try to debug your formula in order to understand what is wrong.

AshRaghav commented 7 years ago

Thanks @ebrehault,

Thanks for pointing me in the right direction. Made me re-evaluate the problem.

My scenario: I am populating the selection list inside the datagrid (different form) and that selection list is causing this error (like you mentioned before). This is the code inside selection list

db = context.getParentDatabase()

url = context.REQUEST.get('ACTUAL_URL') vSubLists = db.getView('vData') SubDocs = vSubLists.getAllDocuments() FinLists = ['Please select...|'] doc = '' docid = '' MainDoc = '' docURL = url.split('/')

docid = docURL[-2] doc = db.getDocument(docid)

if isDocument(doc): MainDoc = doc.getItem('FirstTitle')

for SubDoc in SubDocs: if not MainDoc: IndSubDoc = SubDoc.getItem('SecondTitle') + "|" IndSubDoc += SubDoc.getItem('SecondNo') SubLists.append(IndSubDoc) else: for row in SubDoc.getItem('SubStructureGrid'): if MainDoc and MainDoc in row[1] and \ not SubDoc.getItem('SecondTitle') in FinLists: IndSubDoc = SubDoc.getItem('SecondTitle') IndSubDoc += "|" IndSubDoc += SubDoc.getItem('SecondNo') FinLists.append(IndSubDoc)

return FinLists

With some trial and error the problem appears when I try to save some data inside the Datagrid and I think the problem points to the URL "split" function and getting the document using docID from URL. Not sure why it is getting inconsistent results although I always get the URL from context.

Is there a different way to retrieve the document ID from the URL other than split method?

Unfortunately plominoDocument doesn't work as the Datagrid uses a completely different form to primary form and the selection list populated in Datagrid is based on a selection in the primary form.

Thanks

ebrehault commented 7 years ago

The best way to debug in such a case is to log:

url = context.REQUEST.get('ACTUAL_URL')
Log(url)
docURL = url.split('/')
Log(docURL)

That way, you will see in the server log what are the values of your variables and it will help you to understand the problem.

AshRaghav commented 7 years ago

@ebrehault - thanks again.

I took a different approach of sending the input via URL and getting the value through REQUEST and the values always come through without any issue now. I must admit I felt the method of appending the value in query string was considerably easy and reliable as the value is always there.

I was running against your suggestion for displaying values from Datagrid in a View and interestingly, as you mentioned Views show only one row per document. However, is there a way to make the Datagrid show two or more rows per document?

Obviously because there will be more rows in Datagrid compared to the document and it would be useful to show each Datagrid row as a separate row in the View. So same document will be duplicated depending on the number of Datagrid rows. I tried iterating in a column to see if multiple rows are generated but not very successful with that.

If this is not possible then I will have to Export the data to Excel and look at a quick way of organising the additional Datagrid rows into separate rows.

Sincerely appreciate your guidance all along.

jean commented 7 years ago

@AshRaghav

However, is there a way to make the Datagrid show two or more rows per document?

Just an idea ... the view iterates through the matching records in Plomino's catalog, constrained on PlominoViewFormula_VIEWID (where VIEWID is the id of your view). Plomino updates this catalog with one record per matching document. I think you could update it with additional records per document (e.g. in document on-save events), as long as you take care to match the columns defined for the view.

AshRaghav commented 7 years ago

@jean - thanks for the suggestion. Am I right in understanding your idea about saving additional records during events relates to creating a new document using the same Datagrid form which could match with the parent document?

If yes, then I think we have tried doing this before and it is definitely not a bad idea except that we need to ensure the record is consistent and robust as it needs to link back correctly. I will try working this out and come back next week.

We are essentially trying to create one universal form which would otherwise result in at least 100 separate forms to cater the same purpose. Not to mention, we need the completed data exported for further analysis and decision making resulting in this level of complexity.

I am quite liking Plone and Plomino though because of the ease of building things without writing every single piece of code (commendable Abstraction!) :-)

All your help is much appreciated.