Update child table using REST

you are not using Double quotes in your Parameters…
please copy paste below to test your URL

data = {
“items”: [
{
“item_code”: “DON P551422”
}]
}

Try data as string and not as a dict.

E.g. request.put(url, data=json.dumps(data), headers=headers)

Also,

If you’re using OAuth2

headers = {
    "Authorization":"Bearer " + access_token
}

Header must have token for the request to be valid.

Checkout account_manager.py, I’ve tried to replicate Android’s AccountManager getAuthToken here.

Token is stored and replaced either as DocType or as key in redis cache. Default is DocType.

Edit: for rauth

session.put(‘http://[URL]/api/resource/Cart/City%20Generators%20LLC’, params=json.dumps(data))

2 Likes

@revant_one
I tried

request.put(url, data=json.dumps(data), headers=headers)

and it return CODE 200 but it does not update, it return the data of City Generators LLC .

When I try the second way I get the same error

I don’t think it makes any difference, but I tried it and I get the same error.

Can you try 2 requests, one for parent DocType and one for child
E.g

/api/resource/Cart/<name> for parent and
/api/resource/Cart Item/<name> for child

Alternatively add a whitelisted method in your custom frappe app and call that endpoint

@revant_one I did the second one. It took two days and I was not gonna spend more time with it. Thank You. Meanwhile, can you do POST and PUT requests and your ERPNext if this might be ERP problem?
I have:
ERPNext: v8.x.x-beta (cf36534) (develop)
Frappe Framework: v8.10.7 (master)

@revant_one can i use FrappeClient on python 3? Because I am having AuthError on PyCharm

Latest frappeclient.py has FrappeOAuth2Client frappe/frappeclient.py at develop · frappe/frappe · GitHub

Can you make the frappe/frappe-client 2 and 3 compatible also add FrappeOAuth2Client there?

I can not do pip install on frappe. (PyCharm)
This is the error I am having:

_mysql.c:29:10: fatal error: ‘my_config.h’ file not found
#include “my_config.h”
^
1 error generated.
error: command ‘clang’ failed with exit status 1

----------------------------------------

Command “/Users/aldoec/.virtualenvs/ECStoreVirtualEnv/bin/python3.6 -u -c “import setuptools, tokenize;file=‘/private/var/folders/93/7d2wj24d0cv7xnrph6ymcj2r0000gn/T/pip-build-nymuea28/mysqlclient/setup.py’;f=getattr(tokenize, ‘open’, open)(file);code=f.read().replace(‘\r\n’, ‘\n’);f.close();exec(compile(code, file, ‘exec’))” install --record /var/folders/93/7d2wj24d0cv7xnrph6ymcj2r0000gn/T/pip-k19oba59-record/install-record.txt --single-version-externally-managed --compile --install-headers /Users/aldoec/.virtualenvs/ECStoreVirtualEnv/bin/…/include/site/python3.6/mysqlclient” failed with error code 1 in /private/var/folders/93/7d2wj24d0cv7xnrph6ymcj2r0000gn/T/pip-build-nymuea28/mysqlclient/

The idea is that the webapp that is using OAuth is going to be hosted in another server and ERPNext in another server

by that I mean run the code through 2to3, Cheat Sheet: Writing Python 2-3 compatible code — Python-Future documentation, add the FrappeOAuth2Client related classes and send a pull request.

FrappeOAuth2Client extends FrappeClient and OAuth2Session is used instead of requests.session

class FrappeOAuth2Client(FrappeClient):
	def __init__(self, url, access_token, verify=True):
		self.access_token = access_token
		self.headers = {
			"Authorization": "Bearer " + access_token,
			"content-type": "application/x-www-form-urlencoded"
		}
		self.verify = verify
		self.session = OAuth2Session(self.headers)
		self.url = url

	def get_request(self, params):
		res = requests.get(self.url, params=self.preprocess(params), headers=self.headers, verify=self.verify)
		res = self.post_process(res)
		return res

	def post_request(self, data):
		res = requests.post(self.url, data=self.preprocess(data), headers=self.headers, verify=self.verify)
		res = self.post_process(res)
		return res

class OAuth2Session():
	def __init__(self, headers):
		self.headers = headers
	def get(self, url, params, verify=True):
		res = requests.get(url, params=params, headers=self.headers, verify=verify)
		return res
	def post(self, url, data, verify=True):
		res = requests.post(url, data=data, headers=self.headers, verify=verify)
		return res
	def put(self, url, data, verify=True):
		res = requests.put(url, data=data, headers=self.headers, verify=verify)
		return res

difference in use,

client = FrappeOAuth2Client("https://example.com", "oDgbZLjj8VaccessTokenSIKm9YFkQ")

instead of

client = FrappeClient("example.com", "user@example.com", "password")

Is your other webapp based on Django?

I’ve managed to do same where both servers host frappe app. Read More

1 Like

@revant_one I did it. Sometimes I talk before I act. I’m sorry. I added FrappeOAuth2Client . I’m gonna test it a little bit more before doing a pull request.

Yes, my code is Django on Python 3. Thank You.

I have same issues.
I want to update sub child table row
http://instances/api/resource/Customer/CUST-00025/?data={“customer_sub_profile”:[{“full_name”: “ram”,“date_of_birth”:“1993-10-23”]}}

This actually works when you pass the parentfield and parenttype into the api call. see example below

from frappeclient import FrappeClient

conn = FrappeClient("http://www.example.com:8000")
conn.authenticate("api_key", "api_secret")

doc = conn.insert({
    "doctype": "DocType",
    "field_name":"value",
    .
    .
    "child_table_field_name": [{"parentfield": "child_table_field_name", "parenttype": "DocType","column_name":"value",..........,"doctype": "Child Table DocType"}]
})

print(doc)

Note : child_table_field_name is the name of the child table in your parent doctype

1 Like