I'm using python to edit my Trello cards - specifically, I'm trying to update Custom Field values on the cards.
My python script can set the value of the field to "" just fine, but when I try to set the value to a non-empty-string, it gives an error:
'Invalid custom field item value.', 'error': 'ERROR'
I think it might be something to do with encoding, but after trying to encode the value dict to json, and set the requests header to "application/json", both to no avail, I'm out of ideas.
Can anyone help me with this?
Code:
def trello_card_update_custom_field(card_id, custom_field_id, custom_field_value):
url = "https://api.trello.com/1/cards/{card_id}/customField/{custom_field_id}/item".format(card_id=card_id, custom_field_id=custom_field_id)
querystring = {
"key": key,
"token": token,
"value": {'text': 'this is a new string'}
#"value": ""
}
response = requests.request("PUT", url, params=querystring)
response_json = response.json()
return response_json
# end function
update_trello_card = trello_card_update_custom_field(card_id, custom_field_id, custom_field_value)
print("updated trello card. json response:\n", update_trello_card)
Here's the link to this function in the documentation: https://developer.atlassian.com/cloud/trello/rest/#api-cards-idCard-customField-idCustomField-item-put
edit - I tried changing the nested dict part of the request:
"value": {'text': 'this is a new string'}
to just:
'text': 'this is a new string'
But I got this error:
Traceback (most recent call last):
File "test_trello.py", line 153, in <module>
update_trello_card = trello_card_update_custom_field_path_auth (card_id, custom_field_id, custom_field_value)
File "test_trello.py", line 129, in trello_card_update_custom_field_path_auth
response_json = response.json()
File "C:\Users\andre\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\requests\models.py", line 897, in json
return complexjson.loads(self.text, **kwargs)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2032.0_x64__qbz5n2kfra8p0\lib\json\__init__.py", line 348, in loads
return _default_decoder.decode(s)
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2032.0_x64__qbz5n2kfra8p0\lib\json\decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2032.0_x64__qbz5n2kfra8p0\lib\json\decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
I also tried editing the request to:
'value': 'this is a new string'
But I got this error:
updated trello card custom field. json response:
{'message': 'Invalid custom field item value.', 'error': 'ERROR'}
I also tried sending the field value as a 'data' kwarg, rather than in the 'params' kwarg, but it made no difference.
I have had the same issue and am happy to present you with a working solution (my first ever answer on this site 😊).
Your response defintion: response = requests.request("PUT", url, params=querystring)
You need to amend it like so:
response = requests.request("PUT", url, json=querystring)
Here is my function:
def update_custom_field(card_id,custom_field_id,value_type,value):
url = f'https://api.trello.com/1/card/{card_id}/customField/{custom_field_id}/item'
payload = {'token':token,'key':key,'value':{value_type: value}}
request = requests.put(url,json=payload)
return request.text
update_custom_field(card_id,custom_field_id,'text','hello word!')```
def trello_card_update_custom_field(card_id, custom_field_id, custom_field_value):
url = "https://api.trello.com/1/cards/{card_id}/customField/{custom_field_id}/item".format(card_id=card_id, custom_field_id=custom_field_id)
querystring = {
"key": key,
"token": token,
}
body = {'text': 'this is a new string'}
response = requests.request("PUT", url, data=body, params=querystring)
response_json = response.json()
return response_json
body=
{
"value": {
"text": "<string>",
"checked": true,
"date": "2018-03-13T16:00:00.000Z",
"number": 2154
}
}
try this body instead
also refers to here:
https://developer.atlassian.com/cloud/trello/rest/#api-cards-idCard-customField-idCustomField-item-put
and click body parameters example
Related
I am trying to implement, using flask-restx, an endpoint which will take both formData (a list of files to be more precise) and a body as json. My code looks as follow:
Multiple files param in some module:
def authorization_param(ns: Namespace, parser: Optional[RequestParser] = None) -> RequestParser:
if not parser:
parser = ns.parser()
parser.add_argument('Authorization', location='headers', required=False, default='Bearer ')
return parser
def multiple_file_param(arg_name: str, ns: Namespace, parser: Optional[RequestParser] = None) -> RequestParser:
if not parser:
parser = ns.parser()
parser.add_argument(arg_name, type=FileStorage, location='files', required=True, action='append')
return parser
Model:
some_form_model = api.model('form', {'field': fields.String())
And the endpoint itself:
ns = Namespace('sth', description='Some stuff'))
auth_param = authorization_param(ns=ns)
file_param = multiple_file_param(arg_name='File', ns=ns)
#ns.route('/files')
#ns.expect(auth_param)
class PreprocessFiles(Resource):
#ns.response(code=201, description='Job created', model=some_model)
#ns.response(code=400, description='Bad request', model=None)
#ns.response(code=401, description='Authentication Error', model=None)
#ns.response(code=403, description='Forbidden', model=None)
#ns.response(
code=422,
description='Input data validation Error',
model=some_model
)
#ns.expect(some_form_model)
#ns.expect(file_param)
def post(self):
payload = request.get_json()
# do some stuff..
return {'text': 'ok'}, 201
The endpoint is registered in an API object:
api.add_namespace(ns)
My problem is that in swagger I get either input body or file parameter, depending on the order of decorators I use. If I try to pass both form model and file param into one ns.expect as so
#ns.expect(some_form_model, file_param)
I get the following error in the console and the schema is not rendered:
2022-08-26 12:19:45.764 ERROR flask_restx.api api.__schema__: Unable to render schema
Traceback (most recent call last):
File "D:\Project\venv\lib\site-packages\flask_restx\api.py", line 571, in __schema__
self._schema = Swagger(self).as_dict()
File "D:\Project\venv\lib\site-packages\flask_restx\swagger.py", line 239, in as_dict
serialized = self.serialize_resource(
File "D:\Project\venv\lib\site-packages\flask_restx\swagger.py", line 446, in serialize_resource
path[method] = self.serialize_operation(doc, method)
File "D:\Project\venv\lib\site-packages\flask_restx\swagger.py", line 469, in serialize_operation
if any(p["type"] == "file" for p in all_params):
File "D:\Project\venv\lib\site-packages\flask_restx\swagger.py", line 469, in <genexpr>
if any(p["type"] == "file" for p in all_params):
KeyError: 'type'
Is there any way to go around this? I would really like to have good swagger docs for the frontend folks.
Thanks in advance!
Best,
Mateusz
Hi I'm trying amadeus api flight offer search api but getting 400 error, cross checked my client and secret ID and its correct not sure is there any issue with api or what.
code:
from amadeus import Client, ResponseError, Location
import json
AMADEUS = Client(
client_id='my client id',
client_secret='my secret'
)
try:
response = AMADEUS.shopping.flight_offers_search.get(
originLocationCode='MAD',
destinationLocationCode='ATH',
departureDate='2022-07-26')
resp = json.dumps(response.data, indent=4)
resp = json.loads(resp)
# print(resp)
print(resp)
except ResponseError as error:
print(error)
Exception:
File "C:\Users\ASUS\python_workspace\python_practiceCode\test_file.py", line 261, in <module>
response = AMADEUS.shopping.flight_offers_search.get(
File "C:\Users\ASUS\AppData\Local\Programs\Python\Python39\lib\site-packages\amadeus\shopping\_flight_offers_search.py", line 32, in get
return self.client.get('/v2/shopping/flight-offers', **params)
File "C:\Users\ASUS\AppData\Local\Programs\Python\Python39\lib\site-packages\amadeus\mixins\http.py", line 40, in get
return self.request('GET', path, params)
File "C:\Users\ASUS\AppData\Local\Programs\Python\Python39\lib\site-packages\amadeus\mixins\http.py", line 110, in request
return self._unauthenticated_request(
File "C:\Users\ASUS\AppData\Local\Programs\Python\Python39\lib\site-packages\amadeus\mixins\http.py", line 126, in _unauthenticated_request
return self.__execute(request)
File "C:\Users\ASUS\AppData\Local\Programs\Python\Python39\lib\site-packages\amadeus\mixins\http.py", line 152, in __execute
response._detect_error(self)
File "C:\Users\ASUS\AppData\Local\Programs\Python\Python39\lib\site-packages\amadeus\mixins\parser.py", line 16, in _detect_error
self.__raise_error(error, client)
File "C:\Users\ASUS\AppData\Local\Programs\Python\Python39\lib\site-packages\amadeus\mixins\parser.py", line 67, in __raise_error
raise error
amadeus.client.errors.ClientError: [400]
In your API call, you are missing the mandatory parameter adults. Please check out the API reference for more details.
import paypalrestsdk
import httpx
class paypal:
def __init__(self):
self.secret_id = 'XXXX'
self.client_id = 'XXXX'
self.token = ''
def getToken(self):
headers = {
'Accept': 'application/json',
'Accept-Language': 'en_US',
}
data = {
'grant_type': 'client_credentials'
}
response = httpx.post(url='https://api.sandbox.paypal.com/v1/oauth2/token', data=data,headers=headers,auth=(self.client_id,self.secret_id))
response_data = response.json()
self.token = response_data['access_token']
def getBalance(self):
print(self.token)
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer '+self.token,
'Accept':'application/x-www-form-urlencoded'
}
response = httpx.post(url='https://api.sandbox.paypal.com/v2/wallet/balance-accounts', headers=headers)
print(response.status_code)
response_data = response.json()
print(response_data)
available = response_data['total_available'][0]['value']
print(response_data)
if __name__ == "__main__":
s = paypal()
s.getToken()
s.getBalance()
I am gettitng 404 code i am doing something bad?
Traceback (most recent call last):
File "C:/Users/localhost/PycharmProjects/Telegram/paypal/Main.py", line 48, in <module>
s.getBalance()
File "C:/Users/localhost/PycharmProjects/Telegram/paypal/Main.py", line 37, in getBalance
response_data = response.json()
File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\site-packages\httpx\models.py", line 899, in json
return jsonlib.loads(self.text, **kwargs)
File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\json\__init__.py", line 348, in loads
return _default_decoder.decode(s)
File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\json\decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "C:\Users\localhost\AppData\Local\Programs\Python\Python37\lib\json\decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
404
https://developer.paypal.com/docs/limited-release/balance-accounts/v2/api/
I try also with
"Authorization: Access-Token" But the response is the same, i readed and searched in the docs, i dont found anything and the acces token is fresh so i dont understand, cause the acces token i get is valid.
You are sending a POST request instead of a GET request. Use httpx.get instead of httpx.post.
You can even use httpx_auth to keep your code focusing on what you want to retrieve:
import paypalrestsdk
import httpx
import httpx_auth
class paypal:
def __init__(self):
self.auth = httpx_auth.OAuth2ClientCredentials(
token_url='https://api.sandbox.paypal.com/v1/oauth2/token',
client_id='XXXX',
client_secret='XXXX',
)
def getBalance(self):
response = httpx.get(url='https://api.sandbox.paypal.com/v2/wallet/balance-accounts', auth=self.auth)
print(response.status_code)
response_data = response.json()
print(response_data)
available = response_data['total_available'][0]['value']
print(response_data)
if __name__ == "__main__":
s = paypal()
s.getBalance()
I am trying to POST request from my flutter application to the Flask REST API, testing API with POST MAN has no problem, but on flutter I am getting error in flutter like this:
I/flutter ( 6378): FormatException: Unexpected character (at character 1)
I/flutter ( 6378):
I/flutter ( 6378): ^
and in Flask APP like this:
[2020-01-23 11:42:32,517] ERROR in app: Exception on /cards [POST]
Traceback (most recent call last):
File "/home/shaukat/.local/lib/python3.7/site-packages/flask/app.py", line 2311, in wsgi_app
response = self.full_dispatch_request()
File "/home/shaukat/.local/lib/python3.7/site-packages/flask/app.py", line 1834, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/shaukat/.local/lib/python3.7/site-packages/flask/app.py", line 1737, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/shaukat/.local/lib/python3.7/site-packages/flask/_compat.py", line 36, in reraise
raise value
File "/home/shaukat/.local/lib/python3.7/site-packages/flask/app.py", line 1832, in full_dispatch_request
rv = self.dispatch_request()
File "/home/shaukat/.local/lib/python3.7/site-packages/flask/app.py", line 1818, in dispatch_request
return self.view_functionsrule.endpoint
File "/home/shaukat/Projects/udemy flask rest API and python/rest-api-sections-master/section3/app.py", line 19, in create_card
'id': request_data["id"],
TypeError: 'NoneType' object is not subscriptable
127.0.0.1 - - [23/Jan/2020 11:42:32] "POST /cards HTTP/1.1" 500 -
My code in flutter:
Future<void> addNewCard(NewCard product) async {
const url = 'http://10.0.2.2:5000/cards';
try {
final response = await http.post(
url,
body: json.encode({
'id': product.id,
'cardNo': product.cardNo,
'cardType': product.cardType,
'amount': product.amount,
}),
);
final newProduct = NewCard(
id: json.decode(response.body)['id'],
cardNo: product.cardNo,
cardType: product.cardType,
amount: product.amount,
);
print(newProduct);
_newCard.add(product);
// _items.insert(0, newProduct); // at the start of the list
notifyListeners();
} catch (error) {
print(error);
throw error;
}}
code in python Flask:
#app.route('/cards', methods=['POST'])
def create_card():
request_data = request.get_json()
new_cards = {
'id': request_data["id"],
'cardNo': request_data["cardNo"],
'cardType': request_data["cardType"],
'amount': request_data["amount"],
}
cards.append(new_cards)
return jsonify(cards)
I eventually found the solution in a comment of this post Flutter POST request body not sent
I had to add headers: {"Content-Type": "application/json"}
in my post request. thanks for your help
line 19, in create_card 'id': request_data["id"], TypeError: 'NoneType' object is not subscriptable
As you see the server is unable to get the data / parse it.
I'd suggest to debug it inside the REST server and check if you are even receving the values..
I understand that postman works for you, but once you understand what are you even getting # the server it will be easier to fix what flutter sends.
my guess is that product.id (flutter code) is an int and not a string..
please send a more detailed debug information to help resolve this.
good luck.
I have a script(test.py) to test some api, like this:
def get_response(fct, data, method=GET):
"""
Performs the query to the server and returns a string containing the
response.
"""
assert(method in (GET, POST))
url = f'http://{hostname}:{port}/{fct}'
if method == GET:
encode_data = parse.urlencode(data)
response = request.urlopen(f'{url}?{encode_data}')
elif method == POST:
response = request.urlopen(url, parse.urlencode(data).encode('ascii'))
return response.read()
In terminal I call:
python test.py -H 0.0.0.0 -P 5000 --add-data
The traceback:
Traceback (most recent call last):
File "test.py", line 256, in <module>
add_plays()
File "test.py", line 82, in add_plays
get_response("add_channel", {"name": channel}, method=POST)
File "test.py", line 43, in get_response
response = request.urlopen(url, parse.urlencode(data).encode('ascii'))
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 223, in urlopen
return opener.open(url, data, timeout)
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 532, in open
response = meth(req, response)
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 642, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 570, in error
return self._call_chain(*args)
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 504, in _call_chain
result = func(*args)
File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/request.py", line 650, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 400: BAD REQUEST
The data is {"name": "Channel1"}. I couldn't understand what is wrong. Please can someone give some tip or show whats's wrong?
When I call using curl, works:
curl -X POST -H "Content-Type: application/json" -d '{"name": "Channel1"}' http://0.0.0.0:5000/add_channel
I solved the problem change the test script:
The api was expected a JSON_MIME_TYPE = 'application/json', so I add a header in a request as follow bellow.
The scrit was using a wrong encode because some text in JSON couldn't be encode in Unicode, Eg:"Omö" encode in ascii launch the exception UnicodeEncodeError: 'ascii' codec can't encode character '\xf6' in position 1: ordinal not in range(128). So I changed to utf8.
Here is the fixed code:
def get_response(fct, data, method=GET):
"""
Performs the query to the server and returns a string containing the
response.
"""
assert(method in (GET, POST))
url = f'http://{hostname}:{port}/{fct}'
if method == GET:
encode_data = parse.urlencode(data)
req = request.Request(f'{url}?{encode_data}'
, headers={'content-type': 'application/json'})
response = request.urlopen(req)
elif method == POST:
params = json.dumps(data)
binary_data = params.encode('utf8')
req = request.Request(url
, data= binary_data
, headers={'content-type': 'application/json'})
response = request.urlopen(req)
x = response.read()
return x