Good to see at another lesson! In this unit, we will explore how to handle and validate complex data structures by creating nested schemas. This is an essential skill when dealing with real-world data, which often includes nested relationships such as user profiles with nested address details.
By the end of this lesson, you will be able to:
Let's dive in!
Before we get started, let's briefly recap our basic Flask setup. This time we also introduced address information to our mock database to demonstrate handling nested data more effectively:
Python1from flask import Flask 2 3# Initialize a Flask app instance 4app = Flask(__name__) 5 6# Mock database as a list of dictionaries 7database = [ 8 {"id": 1, "username": "cosmo", "email": "cosmo@example.com", "address": {"street": "123 Cosmic St", "city": "Cosmopolis"}}, 9 {"id": 2, "username": "jake", "email": "jake@example.com", "address": {"street": "456 Jake Blvd", "city": "Jaketown"}}, 10 {"id": 3, "username": "emma", "email": "emma@example.com", "address": {"street": "789 Emma Rd", "city": "Emmaville"}} 11]
Now, let's build on this by adding functionality to handle nested data structures.
First, we need to understand what nested schemas are. Nested schemas allow us to represent and validate complex data structures, where one schema is nested within another. For example, a user may have an address with its own schema.
We'll start by defining an AddressSchema
for handling nested address data:
Python1from marshmallow import Schema, fields 2 3# Define a nested schema for address 4class AddressSchema(Schema): 5 street = fields.Str(required=True) 6 city = fields.Str(required=True)
In this example:
AddressSchema
with two required fields: street
and city
.required=True
argument ensures that both fields must be provided and follow their respective data types (string).Next, we integrate the AddressSchema
into the main UserSchema
to model complex user data that includes address information:
Python1# Define a main schema for user with nested address 2class UserSchema(Schema): 3 id = fields.Int() 4 username = fields.Str(required=True) 5 email = fields.Email(required=True) 6 address = fields.Nested(AddressSchema, required=True) 7 8# Create an instance of the User schema 9user_schema = UserSchema()
In this main schema, we introduce the address
field using fields.Nested()
. This means that the address
field must conform to the structure and validation rules defined in the AddressSchema
, and with the required=True
argument, it ensures that the address field is mandatory.
No changes are needed to our existing POST endpoint, as the validation of both the main UserSchema
and the nested AddressSchema
will happen automatically:
Python1from flask import request, jsonify 2from marshmallow import ValidationError 3 4# Define a route to handle user creation 5@app.route('/users', methods=['POST']) 6def create_user(): 7 try: 8 # Validate the incoming JSON data 9 user_data = user_schema.load(request.get_json()) 10 except ValidationError as err: 11 # Return validation errors as JSON response 12 return jsonify(error=err.messages), 400 13 14 # Generate a new ID by finding the maximum existing ID and adding 1 15 new_id = max(user['id'] for user in database) + 1 16 user_data["id"] = new_id 17 # Add the new user to the mock database 18 database.append(user_data) 19 # Return the newly created user data as JSON response 20 return jsonify(user_data), 201
If the incoming request does not meet the validation criteria defined in the UserSchema
or the nested AddressSchema
, the ValidationError
exception will be raised, and the response will detail the specific validation errors.
For example, if the city
field in the nested address data is missing, the response will look like this:
JSON1{ 2 "error": { 3 "address": { 4 "city": [ 5 "Missing data for required field." 6 ] 7 } 8 } 9}
This response is returned with a 400 status code, indicating invalid data provided by the client.
In this lesson, we learned how to handle and validate complex data structures using nested schemas in Marshmallow
:
With these skills, you're now ready to tackle the practice exercises that follow this lesson. These exercises will give you hands-on experience and reinforce your understanding of nested schemas in Marshmallow
.
Congratulations on making it this far! Keep practicing, and happy coding!