Search code examples
pythonflasksqlalchemyflask-restfulmarshmallow

Marsmhallow ValidationError on _schema - Invalid Input Type


I've been trying to figure out what is causing this input type error but can't seem to figure it out.

models/pin.py

from sqlalchemy import Column, String


class Pin(db.Model):
    __tablename__ = 'pin'

    pin = Column(String, primary_key=True)

schemas/pin.py

from ..models.pin import Pin
from marshmallow import fields, validate


class PinSchema(ma.Schema):
    pin = fields.Str(required=True, validate=[validate.Length(5)])

    class Meta:
        model = Pin
        fields = ('pin')

pin_schema = PinSchema()

resources/pin.py

from flask_restful import Resource
from flask import request
from ..schemas.pin import pin_schema


class PinResource(Resource):

    """
        Update current pin
        Expecting:
        {
            'pin': 'current_pin'
            'new_pin': 'new_pin'
        }
    """
    def patch(self):
        
        data = request.get_json()
        
        errors = pin_schema.validate(data['new_pin'])

        if errors:
            return { "message": errors }, 400

        return { 'tmp': 'tmp' }, 200

Request i'm sending through Postman

{
    "pin": "12345"
    "new_pin": "123456"
}

The response from server

{
    "message": {
        "_schema": [
            "Invalid input type."
        ]
    }
}

I've tried to check the type of new_pin with type(new_pin) and that just returns <class 'str'>

Am I missing something? Shouldn't new_pin pass validation unless it's not castable into a string or shorter than 5 characters?

I've looked at This as this is the only one that I have found that is similar to mine but it doesn't seem to match my case.


Solution

  • PinSchema expects an input like

    {'pin': '2465735452347'}
    

    while you're passing it

    '2465735452347'
    

    You could adapt the input by embeddeding it into a dict to match expected structure.

    Better, you could define a resource input schema that would expect

    {
        'pin': {'pin': '2465735452347'},
        'new_pin': {'pin': '2465735452347'},
    }
    

    so you can check the whole input at once.