Home > Mobile >  object of type 'NoneType' has no len() error, cant seem to solve it
object of type 'NoneType' has no len() error, cant seem to solve it

Time:08-11

So, I have created an api that does some functionality on a post request and sends a response back. I've tested it in my local machine and it works perfectly as intended. But on the server, it shows this error.

[Wed Aug 10 16:11:08.124324 2022] File "/var/www/html/caremigration/careapi/views.py", line 3767, in createSalesOrder
[Wed Aug 10 16:11:08.124324 2022] for i in range(len(request.data.get('materials'))):  
[Wed Aug 10 16:11:08.124328 2022] TypeError: object of type 'NoneType' has no len()

I've provided all the details needed and also proof that it works fine in my local machine. Please help me out.

Views.py

@api_view(['GET','POST'])
def createSalesOrder(request):

    ASHOST='*'
    CLIENT='*'
    SYSNR='*'
    USER='*'
    PASSWD='*'
    IT_ITEMS = []
    IT_ITEMS_DESC = []

    if request.method == 'POST':

        try:
            # print(len(request.data.get('materials')))
            for i in range(len(request.data.get('materials'))):
                IT_ITEMS.append({
                    "MATNR": request.data.get('materials')[i]['MAT_desc']['mat_id'],
                    "QUANTITY":float(request.data.get('materials')[i]['quantity']),
                    "UOM":"cm",
                    "RATE":float(request.data.get('materials')[i]['price']),
                    "VALUE":float(request.data.get('materials')[i]['total']),
                    "CURRENCY":"INR"
                })

                IT_ITEMS_DESC.append({
                        "DESC":request.data.get('materials')[i]['MAT_desc']['item']
                })

            # print(IT_ITEMS)

            I_HEADER = {
                "PLANT":request.data.get('plant'),
                "ORD_DATE": datetime.date.today(),
                "SORG":request.data.get('sorg'),
                "DIS_CHNL":request.data.get('distribution_channel'),
                "DIVISION":request.data.get('division'),
                "CUSTOMER":request.data.get('customer_no'),
                "TRANSPORTER":request.data.get('trasnporter'),
                "TRUCK_NUMBER":request.data.get('truck_no'),
                "LR_NUMBER":request.data.get('lr_no'),
                "TRUCK_TYPE":request.data.get('truck_type'),
                "MILK_RUN":request.data.get('milk_run'),
                "PERMIT_NO":request.data.get('permit_no'),
                "PERMIT_DATE":""
                }

            with  connx(ashost=ASHOST, sysnr=SYSNR, client=CLIENT, user=USER, passwd=PASSWD) as conn:
                
                result =  conn.call("ZSS_SALES_ORDER_CREATE",I_HEADER=I_HEADER, IT_ITEMS=IT_ITEMS)
                # print(result)

            command1 = 'INSERT INTO `scrap_master` (`id`, `scrapid`, `internal_order_no`, `plant`, `cust_no`, `cust_name`, `gp_no_permit_no`, `truck_no`, `truck_type`, `gate_pass_no`, `milk_run`, `status`, `message`, `creation_date`, `created_by`) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);'   
            values1 = (None, result['E_INVOICE'], request.data.get('internal_sale_order'), I_HEADER['PLANT'], I_HEADER['CUSTOMER'], request.data.get('customer_name'), I_HEADER['PERMIT_NO'], I_HEADER['TRUCK_NUMBER'], I_HEADER['TRUCK_TYPE'], 'None', I_HEADER['MILK_RUN'], 'SUCCESS', 'asd', I_HEADER['ORD_DATE'], 'asd')
            
            mycursor.execute(command1,values1)
            mydb.commit()

            for idx in range(len(IT_ITEMS)):

                command2 = 'INSERT INTO `scrap_details` (`id`, `scrap_id`, `sno`, `mat_code`, `description`, `quantity`, `rate`, `value`, `sgst`, `cgst`, `total`, `creation_date`, `created_by`) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);'
                values2 = (None, result['E_INVOICE'], idx 1, IT_ITEMS[idx]['MATNR'], IT_ITEMS_DESC[idx]['DESC'], IT_ITEMS[idx]['QUANTITY'], IT_ITEMS[idx]['RATE'], IT_ITEMS[idx]['VALUE'], '0.0', '0.0', '0.0', datetime.date.today(), 'asd')           
                
                mycursor.execute(command2,values2)
                mydb.commit()


            return Response(result, status=status.HTTP_200_OK) 

        except CommunicationError:
            print("Could not connect to server.")
            #raise
        except LogonError:
            print("Could not log in. Wrong credentials?")
            #raise
        except (ABAPApplicationError, ABAPRuntimeError):
            print("An error occurred.")
            #raise
        
        except Exception as err:
            print(err)
    
    else:
        return Response({"message":"Bad Request"}, status=status.HTTP_400_BAD_REQUEST)

Request Object looks like this:

{
    "internal_sale_order": "1",
    "plant": "Z100",
    "customer_no": "100538",
    "customer_name": "",
    "distribution_channel": "ZZ",
    "division": "ZZ",
    "sorg": "Z100",
    "lr_no": "",
    "truck_no": "",
    "truck_type": "",
    "milk_run": "",
    "permit_no": "",
    "permit_date": "",
    "trasnporter": "",
    "materials": [
        {
            "si_no": "1",
            "MAT_desc": {
                "item": "Ventilation, complete",
                "matname": "SCRAP-01",
                "mat_id": "SCRAP-01"
            },
            "quantity": "0",
            "MAT_code": "SCRAP-01",
            "description": "",
            "price": "0",
            "total": "0",
            "Mat_name": "",
            "edit": false
        }
    ]
}

Response in my local Machine (Before POST): enter image description here

Response in my local Machine (Response): enter image description here

CodePudding user response:

What if you try instead:

for i in range(len(request.GET['materials'])):

?

CodePudding user response:

request.data.get('materials') returns None if the materials was not in the POST request. None cannot be used with len() method so you get an error.

I suggest adding a default in get() method call:

for i in range(len(request.data.get('materials', []))):
# ...

This will avoid the error if "materials" are missing from the request.

It is up to you to decide if you want to raise an error if the "materials" key is missing from the request.

To sum up, the core of the problem is that you're not passing "materials" in the POST request. You should see why is that. My best advice is to use a debugger and to inspect the request object in the view method. Make sure you're using POST method in your client.

  • Related