| 312 | === Pre-populating Create-Forms === |
| 313 | |
| 314 | Create-forms can be pre-populated with data by one of these 3 methods: |
| 315 | |
| 316 | 1. model defaults (standard) |
| 317 | 2. values from another record in the database |
| 318 | 3. values provided by the controller |
| 319 | |
| 320 | Model defaults are defined per field and can be set as {{{db.my_table.field.default = value}}} at any time before the REST method is applied (even in the pre-process). |
| 321 | |
| 322 | Values from another record in the database can be used via a URL query like: |
| 323 | |
| 324 | - /my/resource/create?from_record=''id''&from_fields=''fieldname1'',''fieldname2'',... |
| 325 | |
| 326 | The ''id'' of the original record can also be specified as ''tablename.id'', if the original record is in another table. Additionally, fieldnames can be specified as ''fieldname$original_fieldname'' to map between different fieldnames. |
| 327 | |
| 328 | To pre-populate Create-forms from the controller, you can specify the variable {{{populate}}} in the arguments of {{{s3_rest_controller}}}: |
| 329 | |
| 330 | {{{ |
| 331 | output = s3_rest_controller(prefix, resourcename, |
| 332 | populate=dict(fieldname1=value1, |
| 333 | fieldname2=value2)) |
| 334 | return output |
| 335 | }}} |
| 336 | |
| 337 | Instead of a {{{dict}}}, you can also pass a callable object as {{{populate}}}. This will be executed with the current {{{S3Request}}} and the names arguments of {{{s3_rest_controller}}} in order to produce the field/value {{{dict}}}: |
| 338 | |
| 339 | {{{ |
| 340 | def populate(r, **attr): |
| 341 | """ |
| 342 | Helper function to pre-populate create-forms |
| 343 | |
| 344 | """ |
| 345 | |
| 346 | # some code to produce the data |
| 347 | # ... |
| 348 | |
| 349 | # return the dict |
| 350 | return dict(fieldname1=value1, |
| 351 | fieldname2=value2) |
| 352 | |
| 353 | output = s3_rest_controller(prefix, resourcename, |
| 354 | populate=populate) |
| 355 | |
| 356 | return output |
| 357 | }}} |
| 358 | |
| 359 | Note that {{{populate}}} will only be applied in {{{GET}}} requests and only if no record_id is specified. That means, if it uses a separate form to generate the data, you need to revert the request into {{{GET}}} in order to have the create-form pre-populated: |
| 360 | |
| 361 | {{{ |
| 362 | data = None |
| 363 | form = FORM(...some form...) |
| 364 | output = dict(helper_form=form) |
| 365 | if form.accepts(request.vars, session, formname="helper_form"): |
| 366 | output = dict() # remove the helper form |
| 367 | data = Storage(...) # some code to extract the data from the helper form |
| 368 | if data: |
| 369 | request.env.request_method = "GET" # revert to GET if data available |
| 370 | |
| 371 | _output = s3_rest_controller(prefix, resourcename, populate=data) |
| 372 | |
| 373 | if isinstance(_output, dict): |
| 374 | output.update(_output) |
| 375 | else: |
| 376 | output = _output |
| 377 | |
| 378 | return output |
| 379 | }}} |
| 380 | |
| 381 | NB: This construction could be used e.g. to loop in an OCR client into a REST controller. The helper form would then be a file upload form which is displayed alongside with the normal create-form - so the user can either enter data manually and submit the create-form, or first submit a file to pre-populate the create form, and then edit the data and submit the create-form. |