API Address selection

Hi everyone,

I am trying to figure out how feasable it is in a doctype form to have an autocomplete list of addresses in a custom app.

The API call is the below :

"https://api-adresse.data.gouv.fr/search/?q=8+bd+du+port"

There is an autocomplete field type, so I guess that is it, unfortunately, I could not find any doc on that field type.

Many thanks for your help!

@gmeunier you need to write some custom code to fetch results from third party APIs for autocomplete. In this case you need to override default query.

https://frappeframework.com/docs/v14/user/en/guides/app-development/overriding-link-query-by-custom-script#2-calling-a-different-method-to-generate-results

Autocomplete fields can override queries just like link fields. So what you need is:

  1. Python whitelisted function that follows link query function but queries external API instead of DB.
  2. Client script to override query on the field (same as link field)

Thanks a lot Ankush.

So I started to do so:
For a doctype ‘tiers’ I updates the corresponding tiers.js file:

frappe.ui.form.on("Tiers", "onload", function(frm) {
	frm.set_query("adresse", function() {
		return {
			query: "asso.queries.autocomplete_adresse"
		};
	});
});

I also created the corresponding python file with the following code:

@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def autocomplete_adresse(doctype, txt, searchfield, start, page_len, filters):
    return ( 
        {
        'a' : 'pomme',
        'b' : 'poire',
        'c' : 'orange'
        }
       )

At then end I get the following error message:

Traceback (most recent call last):
File “apps/frappe/frappe/app.py”, line 56, in application
response = frappe.api.handle()
File “apps/frappe/frappe/api.py”, line 53, in handle
return _RESTAPIHandler(call, doctype, name).get_response()
File “apps/frappe/frappe/api.py”, line 69, in get_response
return self.handle_method()
File “apps/frappe/frappe/api.py”, line 79, in handle_method
return frappe.handler.handle()
File “apps/frappe/frappe/handler.py”, line 48, in handle
data = execute_cmd(cmd)
File “apps/frappe/frappe/handler.py”, line 86, in execute_cmd
return frappe.call(method, **frappe.form_dict)
File “apps/frappe/frappe/init.py”, line 1596, in call
return fn(*args, **newargs)
File “apps/frappe/frappe/utils/typing_validations.py”, line 33, in wrapper
return func(*args, **kwargs)
File “apps/frappe/frappe/desk/search.py”, line 292, in wrapper
sanitize_searchfield(kwargs[“searchfield”])
KeyError: ‘searchfield’

Well, I am not an IT guy and I have a very poor knowledge of Python. Right now, that is out of my competencies.

Your return statement in the JS side has missing “filters” section.

filters: {"is_service_item": "Yes"}
1 Like

Thank for your reply, unfortunately, that is not it.
With my son we traced the code and on Python side, searchfield, start, page_len, doctype are not transmitted : only txt and query.
Now we are trying to figure out how txt and query are being provided from js to python but have not found out yet.

It is best to examine the working code. Try to find a code in the ERPNext side in Github.

JS Script

frappe.ui.form.on("Tiers", "onload", function(frm) {

	frm.set_query("adresse", function () {
		return {
			query: "asso.queries.autocomplete_adresse",
			filters: {"is_service_item": "Yes"}
		}
	});

});

Request Data

{
	"type": "POST",
	"args": {
		"txt": "",
		"query": "asso.queries.autocomplete_adresse"
	},
	"headers": {},
	"error_handlers": {},
	"url": "/api/method/asso.queries.autocomplete_adresse"
}

Response Data

{
	"exception": "KeyError: 'searchfield'"
}