Prepopulate custom edit form

191 views
Skip to first unread message

Kevin Keller

unread,
Apr 2, 2021, 10:06:27 AM4/2/21
to py4web
Sorry me one last time today.

I am creating a custom form now for some parts of my page that uses multiple tables in one form and I wonder how I can pre-puplate some of the values depending on what record is being edited.

Should I grab the id from the URL, query all the records and then set pydal default values for that form? 

Or how would you go about it? 

E.g. prepoplate this form:

Would you set product_name.default=db(db.product==id).select(product_name)

etc. ?

@action('form_example', method=['GET', 'POST'])
@action.uses('form_example.html', session)
def form_example():
    form = Form([
        Field('product_name'),
        Field('product_quantity', 'integer')],
        formstyle=FormStyleBulma)
    if form.accepted:
        # Do something with form.vars['product_name'] and form.vars['product_quantity']
        redirect(URL('index'))
    return dict(form=form)

Jim Steil

unread,
Apr 2, 2021, 12:09:40 PM4/2/21
to py4web
That is what I would do.

-Jim

Kevin Keller

unread,
Apr 2, 2021, 3:41:41 PM4/2/21
to Jim Steil, py4web
Thanks Jim, will try. 

--
You received this message because you are subscribed to the Google Groups "py4web" group.
To unsubscribe from this group and stop receiving emails from it, send an email to py4web+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/py4web/30b1efb7-1030-4c5d-b212-c8c72e3723e8n%40googlegroups.com.

Massimo

unread,
Apr 11, 2021, 9:31:12 PM4/11/21
to py4web
Indeed you can prepopulate a form field by looking the value up in another table. For example:

# given you know the id  of the product to prepulate
default_name = db(db.product.id==id).select(db.product.product_name)['product_name])
# or shorter
default_name = db.product[id].product_name
form = Form([
   Field('product_name', default=default_name),
   Field('product_quantity', 'integer')], formstyle=FormStyleBulma)

But is this really want you want?

I would rather create a form that posts the product id instead of the product name and get the corresponding name from a list.

options = [(row.id, row.product_name) for row in db(db.product).select())
form = Form([
   Field('product_id', requires=IS_IN_SET(options)),
   Field('product_quantity', 'integer')], formstyle=FormStyleBulma)

Do I make sense?

Kevin Keller

unread,
Apr 13, 2021, 4:22:52 PM4/13/21
to Massimo, py4web
It does thank you. 

I went with a simple pydal query for now and will implement the list version a bit later. 
Just wanted to test it out first. 

It works for the titel, but for dates it does not. The dates are not displayed in the from fields:

How could I make prepolate the date fields properly?

Thanks!

Here is the controller and screenshot:

 presorows = db ((db.presoatslot.id==pid)).select(db.presoatslot.title,db.presoatslot.startdate,db.presoatslot.enddate)
        for rows in presorows:
            db.presoatslot.title.default=rows.title
            db.presoatslot.startdate.default=rows.startdate
            db.presoatslot.enddate.default=rows.enddate
            print (rows.startdate)
        form = Form(([db.presoatslot.title,db.presoatslot.startdate,db.presoatslot.enddate] + [db.speakersatpreso.speaker]),hidden={'presentation':'None','ended':'False'},deletable=False,dbio=False)
        

image.png

--
You received this message because you are subscribed to the Google Groups "py4web" group.
To unsubscribe from this group and stop receiving emails from it, send an email to py4web+un...@googlegroups.com.
image.png

Kevin Keller

unread,
Apr 13, 2021, 4:26:27 PM4/13/21
to py4web
The value is indeed populated but just not displayed:

image.png

Jim Steil

unread,
Apr 13, 2021, 4:28:30 PM4/13/21
to py4web
Kevin

What does the field def look like for those date fields in your db.define_table for the presoatslot table?  Do you specify a date format, or do you use the default?

-Jim

Kevin Keller

unread,
Apr 13, 2021, 4:39:49 PM4/13/21
to Jim Steil, py4web
I use the default..  and I saw there was a "T" missing for the field to pick it up.. 

So hacked around add that T in the field value, but indeed Jim, the time is completely off. 

Plus if I leave the speaker field empty and I get a validation error, all the values are wiped clean as well... 

So not great.. 

for rows in presorows:
            db.presoatslot.title.default=rows.title
            startdate=str(rows.startdate)
            startdate=startdate.replace(" ", "T")
            db.presoatslot.startdate.default=startdate
            enddate=str(rows.enddate)
            enddate=enddate.replace(" ", "T")
            db.presoatslot.enddate.default=enddate

Kevin Keller

unread,
Apr 13, 2021, 4:41:03 PM4/13/21
to py4web
This is the model defition:

I use datetime:

db.define_table(
'presoatslot',
 Field('creator', db.auth_user),
 Field('owner', db.auth_user),
 Field('title'),
 Field ('startdate','datetime'),
 Field('enddate','datetime'),
 Field('ended','boolean'),
 Field ('slot', readable=False, writable=False),
 Field('adhoc','boolean')
    )



Am Di., 13. Apr. 2021 um 22:26 Uhr schrieb Kevin Keller <kell...@gmail.com>:
The value is indeed populated but just not displayed:

image.png

Am Di., 13. Apr. 2021 um 22:22 Uhr schrieb Kevin Keller <kell...@gmail.com>:

Kevin Keller

unread,
Apr 13, 2021, 4:55:54 PM4/13/21
to py4web
Actually, the dates are not off.. it works now .. 

I just thought they were off because my edit form does not write into the database.. but that is another odd issue to solve. 

The date pickup works now with the conversion of the date value to string and adding that T between the date and time value.. 


Kevin Keller

unread,
Apr 13, 2021, 5:01:12 PM4/13/21
to py4web
Yep, my edit form was creating new records... I used the wrong from handler.. 

Will post the full working example once it works.. I think I know now what to do..

Kevin Keller

unread,
Apr 13, 2021, 6:54:09 PM4/13/21
to Jim Steil, py4web
Thanks Jim, yes you are right but it works quite well with setting the defaults. 

Maybe I should use _placeholder instead?

Just discovered in the form.py source.

Never used it.

I also see I the Form.py source that there is also a conversation function for datetime to add the "T".

However it doesn't work if form was instantiated using a field list that happens to have a datetime field in it like in my case.

Hence my workaround, but the workaround is useless if the form values are not valid and the form is not accepted and sent back with the error message. Then the datetime fields are missing the "T" again and are not shown.

I think this is a bug in Form.py.

It only works correctly if the Form uses the fields from instantiatimg with the whole database table.

With a field list datetime field the adding of the "T" doesn't happen.



On Tue, Apr 13, 2021, 23:05 Jim Steil <ato....@gmail.com> wrote:
Oh, also, it looks like you're looping through some records to set the default.  I think that is effectively setting your default to the value from the last record.  The default isn't set per row, it is set on the field once.

Am I reading that correctly?  It's hard to be certain with the poor formatting options that google groups offer.

-Jim

Kevin Keller

unread,
Apr 13, 2021, 7:22:54 PM4/13/21
to Jim Steil, py4web
So in form.py removing the if statements and making sure that the "T" is always applied solves it for me. 

Why do we need this  if isinstance(value, str): in there?

If we need it, can we refine this function so it also applies the "T" for a datetime field that was instantiated in the form as a part of a list? 



elif field.type == "datetime":
149               #  if isinstance(value, str):
150                 value = value.replace(" ", "T")
151                 control = INPUT(
152                     _value=value,
153                     _type="datetime-local",
154                     _id=input_id,
155                     _name=field.name,
156                     _placeholder=placeholder,
157                     _title=title,
158                 )

Kevin Keller

unread,
Apr 13, 2021, 7:31:51 PM4/13/21
to Jim Steil, py4web
I see now what it was for, so in a create form the datetime field would be empty, so adding a "T" to an empty value will run into an error. 

I would propose just to change the if statement to this then:

if value:

150                   value = value.replace(" ", "T")

Just checking if there is a value or not, and not if that value is a string. 

That seemed to cause an issue for me. 

Will do more testing and crearte a PR then. 

Sorry for the spam, will sign off now :) .


Kevin Keller

unread,
Apr 14, 2021, 9:12:06 AM4/14/21
to Jim Steil, py4web
So in the end this works:

Will create an PR.. 

148             elif field.type == "datetime":
149                 helpervalue=str(value)
150                 helpervalue = helpervalue.replace(" ", "T")
151                 control = INPUT(
152                     _value=helpervalue,

153                     _type="datetime-local",
154                     _id=input_id,
155                     _name=field.name,
156                     _placeholder=placeholder,
157                     _title=title,
158                 )
Reply all
Reply to author
Forward
0 new messages