Search code examples
pythonvalidationrestcolanderhttp-patch

Using Colander to validate PATCH requests


EDIT: My original question refered to PUT requests, I have changed it to PATCH based on the answer provided by thecoshman.

I am developing a RESTful webservice using cornice and I have recently discovered colander. My question is related to PATCH requests. I now know PUT requests should be complete records but not so with PATCH requests. Can I use colander to validate json data attached to a PATCH request?

Colander is great for validating POST requests as it ensures I have all the right data in my json and also removes any extraneous data.

Here's my simple schema.

class OrganisationSchemaRecord(MappingSchema):
    orgname = SchemaNode(String())
    fullname = SchemaNode(String())
    description = SchemaNode(String(), missing=drop)

class OrganisationSchema(MappingSchema):
    organisation = OrganisationSchemaRecord()

This allows me to keep my view code simple like this.

@view(validators=(unique,), renderer='json', schema=OrganisationSchema)
def collection_post(self):
    """Adds a new organisation"""
    org = DBOrg(**self.request.validated['organisation'])#sqlalchemy model
    DBSession.add(org)
    return {'organisation': org}

The magic being schema=OrganisationSchema which validates the json body of the request and places is in self.request.validated['organisation'] as per the schema.

It also works great with my other validator which ensures the primary key is not already in use.

def unique(request):
    if 'organisation' in request.validated: #Implies a validated schema
        orgname = request.validated['organisation']['orgname']
        if DBSession.query(DBOrg).get(orgname):
            request.errors.add('url', 'orgname', 'This organisation already exists!')

However, if I want to process a PATCH request to update the fullname or description fields then validation fails unless the request also includes a value for orgname which I don't want to change.

What is the best solution? Do I insist on complete and valid records being PATCHed to the server, do I define a different schema or am I missing something?


Solution

  • honestly, skipped over most of the question, so hopefully I didn't miss anything too big.

    Should PUT requests be full records - Yes, absolutely.

    PUT requests put an entire replacement record at the URI you requested.

    If you want to perform a partial modification, you should use PATCH (which is surprisingly lesser known). Before PATCH, the theory would be, GET the record, modify locally, PUT entire record back