Announcement

Collapse
No announcement yet.

API Question: CRUD List - select with where clause params not recognized / Python

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • rushabh
    replied
    Maybe the api client class for python has an issue. It was contributed and I did not test it. I'm not a python developer.

    Try to change in the client:

    from: kwargs['data'] = params

    to: kwargs['params'] = params

    This will maybe fix the issue.

    Also, still, there is an issue then upgrade pip, python version. There are lots of new APIs now available that will help you to resolve your issue.

    Python requests get() method accepts the config object in which you can set the type, header, etc. It is the best API out there that can help you.

    If you are using the Django framework then crud in Django makes it very easy and you can also create an API very fast.

    I hope this helps.

    Leave a comment:


  • mbaysek
    replied
    yuri The new API class code you sent above has worked. Now that you mention it (in your code,) it makes sense that you'd have to build the GET url query in order to make a request.get call.

    I appreciate the time you put into this. Thank you.

    Leave a comment:


  • yuri
    replied
    Well, I fell into the rabbit hole of python and was surprised how things that are trivial in javascript and PHP are real hurdles in python.

    I fixed the class. Here is the updated class:


    Code:
    import requests
    import urllib
    
    class EspoAPIError(Exception):
        """An exception class for the client"""
    
    def http_build_query(data):
        parents = list()
        pairs = dict()
    
        def renderKey(parents):
            depth, outStr = 0, ''
            for x in parents:
                s = "[%s]" if depth > 0 or isinstance(x, int) else "%s"
                outStr += s % str(x)
                depth += 1
            return outStr
    
        def r_urlencode(data):
            if isinstance(data, list) or isinstance(data, tuple):
                for i in range(len(data)):
                    parents.append(i)
                    r_urlencode(data[i])
                    parents.pop()
            elif isinstance(data, dict):
                for key, value in data.items():
                    parents.append(key)
                    r_urlencode(value)
                    parents.pop()
            else:
                pairs[renderKey(parents)] = str(data)
    
            return pairs
        return urllib.parse.urlencode(r_urlencode(data))
    
    class EspoAPI:
    
        url_path = '/api/v1/'
    
        def __init__(self, url, username, password):
            self.url = url
            self.username = username
            self.password = password
            self.status_code = None
    
        def request(self, method, action, params=None):
            if params is None:
                params = {}
    
            headers = {
            }
    
            kwargs = {
                'url': self.normalize_url(action),
                'auth': (self.username, self.password),
                'headers': headers,
            }
    
            if method in ['POST', 'PATCH', 'PUT']:
                kwargs['json'] = params
            else:
                kwargs['url'] = kwargs['url'] + '?' + http_build_query(params)
    
            response = requests.request(method, **kwargs)
    
            self.status_code = response.status_code
    
            if self.status_code != 200:
                reason = self.parse_reason(response.headers)
                raise EspoAPIError('Wrong request, status code is {response.status_code}, reason is {reason}')
    
            data = response.content
            if not data:
                raise EspoAPIError('Wrong request, content response is empty')
    
            return response.json()
    
        def normalize_url(self, action):
            return self.url + self.url_path + action
    
        @staticmethod
        def parse_reason(headers):
            if 'X-Status-Reason' not in headers:
                return 'Unknown Error'
    
            return headers['X-Status-Reason']
    Last edited by yuri; 04-18-2020, 09:34 AM.

    Leave a comment:


  • telecastg
    replied
    I am not a Python developer either but I recently wrote an API in python and found python's "request" module very easy to use instead of using the contributed wrap class.

    Here's a good post detailing how to do that: https://forum.espocrm.com/forum/deve...as-a-parameter

    Leave a comment:


  • yuri
    replied
    It looks correct. Try to make the same request through EspoCRM UI and check what params are sent. You can print $params variable to compare what is sent: https://github.com/espocrm/espocrm/b...ecord.php#L132


    Maybe the api client class for python has an issue. It was contributed and I did not test it. I'm not a python developer.

    Try to change in the client:

    from: kwargs['data'] = params

    to: kwargs['params'] = params

    Please let me know if if works so I will fix the class.
    Last edited by yuri; 04-18-2020, 07:39 AM.

    Leave a comment:


  • mbaysek
    replied
    yuri I have tried that, as well. Currently, when trying the format that you specified above, I am still getting a dump of all records in my Lead database.

    Here's my current try at setting the params. :

    Code:
    phone = "555-555-1212"   
    params = {
            "select": "id",
            "where": [
                    {
                        "type": "equals",
                        "attribute": "phoneNumber",
                        "value": phone,
                    }
                ],
        }
    As a check to see if the clause was being parsed at all, I set the type to "foo", and also set the attribute to "foo", and it doesn't even throw any error.

    For debugging, inside the EspoAPI class, I have put some printouts that show the values in params:

    Code:
        def request(self, method, action, params=None):
            if params is None:
                params = {}
    
            print("--------------------------------")
            print("method %s" % method)
            print("action %s" % action)
            print("params: %s" % params)
            print("self %s" % self)
            print("--------------------------------")[INDENT]
    # snip ...[/INDENT]


    printout:
    Code:
    --------------------------------
    method GET
    action Lead
    params: {'select': 'id', 'where': [{'type': 'equals', 'attribute': 'phoneNumber', 'value': '555-555-1212'}]}
    self <espoapi.EspoAPI object at 0x7f259090b400>
    --------------------------------
    Is there something else I must do in order to get the API to recognize my params?

    Leave a comment:


  • yuri
    replied
    "Where" should be an array.

    How it would look in JSON:
    Code:
    [
        {
              "type": "equals",
              "attribute": "phoneNumber",
              "value": "SOME NUMBER"
         }
    ]

    Leave a comment:


  • telecastg
    replied
    I believe that the 'type' in the 'where' clause should be 'equals' instead of 'contains'

    Leave a comment:


  • API Question: CRUD List - select with where clause params not recognized / Python

    I'm trying to query EspoCRM for any leads that might have a particular phone number. I am pretty sure my code is written correctly when I compare it to the PHP API example as a template (https://github.com/espocrm/documenta...arch-params.md)

    No matter what values I pass or format I try for the params or where clause, they do not seem to be recognized. When I run this, I just get a list of all Leads in my CRM. I expect that my where and select clauses should be honored.

    At the end of the day, when I'm done with this function, it will return the id of the lead that contains the phone number. I'd like to do as much of that processing inside the EspoCRM server by passing it the correct search parameters. I hope I don't have to resort to parsing the whole lead list in my code every time I run this function.

    Is there something wrong with what I am doing?

    My code:

    Code:
    #!/usr/bin/python3
    
    import espoapi as crm
    
    endpoint = "https://myendpoint"
    client = crm.EspoAPI(endpoint, "my-api-key")
    
    def check_if_lead_exists_by_number_in_crm(phone: str):[INDENT]where = { 'value': {[/INDENT][INDENT=3]'type': 'contains',
    'attribute': 'phoneNumber',
    'value': phone[/INDENT][INDENT=2]}[/INDENT][INDENT]
    }
    params = {[/INDENT][INDENT=2]'select': 'id',
    'where': where,[/INDENT][INDENT]}
    
    a = "Lead"
    r = client.request('GET', a, params )
    total = r.get("total")
    list = r.get("list")
    print("Total: %s" % total)
    for record in list:[/INDENT][INDENT=2]print("Record: %s" % record)[/INDENT]
    Last edited by mbaysek; 04-04-2020, 02:31 AM.
Working...
X