Automate Marketing Initiatives with Salesforce Marketing Cloud Learn More
Exploring GraphQL with FastAPI A Practical Guide to begin with

Exploring GraphQL with FastAPI: A Practical Guide to begin with

Want to create your own AI Model ?

GraphQL serves as a language for asking questions to APIs and as a tool for getting answers from existing data. It’s like a translator that helps your application talk to databases and other systems. When you use GraphQL, you’re like a detective asking for specific clues – you only get what you ask for. 

Why Choose GraphQL?

GraphQL is pretty cool because it fixes some common problems we face with traditional ways of getting data (like REST APIs). Here’s why: 

  • Get Exactly What You Need: No more getting extra info you don’t want or missing out on stuff you do.
  • Flexible Requests: You can ask for different things in one go, saving time and making things simpler.
  • Easy Development: Imagine having just one stop for all your data needs – that’s GraphQL! It’s like a super organized library where everything has its place.
  • Clear Rules: GraphQL sets clear rules between your app and the servers, making sure everyone understands each other perfectly.
  • Better Performance: By sending only what’s necessary, GraphQL makes your app faster, especially on phones or slow connections. 

Database Connectivity with GraphQL 

GraphQL makes it easy to connect to databases and perform operations. Here, MySQL storage is used, and SQLAlchemy helps integrate seamlessly. 


Enhancing GraphQL with Strawberry 


Strawberry adds extra functionality to GraphQL functions, including queries, types, fields, and mutations. It even supports file uploads within queries. 

Exploring GraphQL with FastAPI: A Practical Guide to begin with

To utilize GraphQL with FastAPI, the process involves several steps: 

  1. Installation: Begin by installing the necessary packages using the provided command: pip install strawberry-GraphQL uvicorn fastapi mysql-connector-python SQLAlchemy.

  2. Database Setup: Begin by establishing a connection to the database to enable operations. In this example, MySQL is utilized for storage, and SQLAlchemy facilitates connectivity to the MySQL database as ORM. This setup typically involves creating a database.py file to manage the connection and a models.py file defining the table columns for the database. 

database.py 

				
					from sqlalchemy import create_engine 

from sqlalchemy.ext.declarative import declarative_base 

from sqlalchemy.orm import sessionmaker 

DB_USER = graphql_query_user 

DB_HOST = 'localhost' 

DB_PORT = '3306' 

DB_NAME = 'user_data' #Enter the database name 

DB_PASSWORD = '*****' 

# MySQL connection URL 

SQLALCHEMY_DATABASE_URL = 

 f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}/{DB_NAME}" 

engine = create_engine(SQLALCHEMY_DATABASE_URL) 

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) 

Base = declarative_base() 

 
				
			

models.py 

				
					from database import Base 

from sqlalchemy import Column, Integer, String 

from database import engine 

class User(Base): 

    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True) 

    firstName = Column(String(255)) 

    lastName = Column(String(255)) 

    age = Column(Integer) 

    gender = Column(String(10)) 

    email = Column(String(255)) 

    phone = Column(String(20)) 

    username = Column(String(255)) 

    password = Column(String(255)) 

# Create the tables in the database 

Base.metadata.create_all(bind=engine) 

 
				
			

Defining Schemas: Once connected to the database, define the schema for the User in a schemas.py file. This schema outlines the structure of the User data that will be handled by GraphQL. 

schemas.py 

				
					import strawberry 

@strawberry.type 

class UserType: 

    id: int 

    firstName: str 

    lastName: str 

    age: int 

    gender: str 

    email: str 

    phone: str 

    username: str 

    password: str 

@strawberry.type 

class DeleteUserResponse: 

    success: bool 

    message: str 
				
			

CRUD Operations: Implement the CRUD (Create, Read, Update, Delete) operations in a crud.py file. This involves defining functions to handle operations such as fetching all users, retrieving a user by their ID, updating, deleting, and creating users. These operations are typically categorized under the Query and Mutation types in GraphQL.  

crud.py 

				
					from models import User 

import strawberry 

from strawberry.extensions import FieldExtension 

from typing import List, Any, Callable 

from database import SessionLocal 

from schemas import UserType, DeleteUserResponse 

@strawberry.type 

class Query: 

    @strawberry.field 

    async def users(limit: int = 10, offset: int = 0) -> List[UserType]: 

        db = SessionLocal() 

        users = db.query(User).offset(offset).limit(limit).all() 

        db.close() 

        return users 

    @strawberry.field 

    async def user_by_id(id: int) -> UserType: 

        db = SessionLocal() 

        user = db.query(User).filter(User.id == id).first() 

        db.close() 

        return user 
				
			
  • The Query class, adorned with @strawberry.type, encompasses two GraphQL query functions responsible for fetching user data from the database.
  • The users function retrieves user details from the database, allowing optional parameters limit and offset to specify the number of users returned and the starting index respectively. Upon execution, it opens a session with the database, queries for users with the specified limit and offset, closes the session, and returns the fetched users as a list of UserType.
  • The user_by_id function retrieves user details based on the provided id, opening a session with the database, querying for a user with the matching id, closing the session, and returning the user details corresponding to the provided id as a single UserType. These functions enable efficient data retrieval, catering to scenarios such as fetching all users or accessing details of a specific user by their ID. 
				
					@strawberry.type 

class Mutation: 

    @strawberry.mutation 

    async def create_user(firstName: str, lastName: str, age: int, gender: str, email: str, phone: str, username: str, password: str) -> UserType: 

        db = SessionLocal() 

        new_user = User(firstName=firstName, lastName=lastName, age=age, gender=gender, email=email, phone=phone, username=username, password=password) 

        db.add(new_user) 

        db.commit() 

        db.refresh(new_user) 

        db.close() 

        return new_user 

    @strawberry.mutation 

    async def update_user(id: int, firstName: str, lastName: str, age: int, gender: str, email: str, phone: str, username: str, password: str) -> UserType: 

        db = SessionLocal() 

        user = db.query(User).filter(User.id == id).first() 

        if user: 

            user.firstName = firstName 

            user.lastName = lastName 

            user.age = age 

            user.gender = gender 

            user.email = email 

            user.phone = phone 

            user.username = username 

            user.password = password 

            db.commit() 

            db.refresh(user) 

        db.close() 

        return user 

    @strawberry.mutation 

    async def delete_user(id: int) -> DeleteUserResponse: 

        db = SessionLocal() 

        user = db.query(User).filter(User.id == id).first() 

        if user: 

            db.delete(user) 

            db.commit() 

            db.close() 

            return DeleteUserResponse(success=True, message=f"User with ID {id} deleted successfully.") 

        else: 

            db.close() 

            return DeleteUserResponse(success=False, message=f"User with ID {id} not found.") 
				
			

The Mutation class, decorated with @strawberry.type, defines three GraphQL mutation functions to create, update, and delete user data in the database. 

  • The create_user mutation function asynchronously creates a new user with the provided parameters – first name, last name, age, gender, email, phone, username, and password. Upon execution, it establishes a connection to the database, adds the new user, commits the transaction, refreshes the database to reflect changes, and finally closes the session before returning the newly created user.

  • The update_user mutation function updates an existing user’s details based on the provided id and other parameters. It begins by querying the database for the user with the matching id, and if found, updates the user’s attributes with the new values. It commits the changes, refreshes the database, closes the session, and returns the updated user. If no user with the provided id is found, it returns None.

  • The delete_user mutation function deletes a user from the database based on the provided id. It starts by querying the database for the user with the specified id. If the user exists, it deletes the user, commits the transaction, and returns a success message along with a boolean indicating successful deletion. If no user is found with the provided id, it returns a failure message stating that the user was not found. Finally, it closes the database session before returning the response. These mutation functions provide essential functionalities for managing user data within the application. 

Schema Definition: Define the schema using Strawberry, specifying the mutations and queries that correspond to the CRUD operations implemented in the crud.py file. 

				
					schema = strawberry.Schema(query=Query,mutation=Mutation) 
				
			

6. FastAPI Endpoint Creation: Create a FastAPI endpoint at “/graphql” to handle    GraphQL mutations. Use add_route to integrate the GraphQL functionality provided by Strawberry into your FastAPI application. 

main.py 

				
					from fastapi import FastAPI 

from strawberry.asgi import GraphQL 

from crud import schema 

app = FastAPI() 

graphql_app = GraphQL(schema) 

# Add GraphQL routes to FastAPI app 

app.add_route("/graphql", graphql_app) 
				
			

7.  Running the Application: Execute the command uvicorn main:app –reload to  run     the application. After running, access it at http://localhost:8000/GraphQL. You can perform queries directly within the GraphQL body in Postman. 
 

Query to Execute: 

				
					# Query to get user by id 

query{ 

  userById(id: 1){ 

    firstName 

    lastName 

    email 

    password 

  } 

} 

# Query to get users details 

query{ 

  users{ 

    id 

    firstName 

    lastName 

    email 

  } 

} 

# Query to create user 

mutation { 

  createUser( 

    firstName: "John" 

    lastName: "Doe" 

    age: 30 

    gender: "Male" 

    email: "john.doe@example.com" 

    phone: "1234567890" 

    username: "johndoe" 

    password: "password123" 

  ) { 

    id 

    firstName 

    lastName 

    age 

    gender 

    email 

    phone 

    username 

  } 

} 

# Query to delete user 

mutation { 

  deleteUser(id: 23) { 

   success 

   message 

  } 

} 

# Query to update user details 

mutation { 

  updateUser( 

    id: 21 

    firstName: "John" 

    lastName: "Doe" 

    age: 30 

    gender: "Male" 

    email: "john.doe@example.com" 

    phone: "1234567890" 

    username: "johndoe" 

    password: "password123" 

  ) { 

    id 

    firstName 

    lastName 

    age 

    gender 

    email 

    phone 

    username 

  } 

} 
				
			

Here’s a screenshot from Postman showing the testing of fetching a user by their ID using GraphQL

GraphQL

File upload with GraphQL

  • Install the required packages using this command  – pip install strawberry-GraphQL  uvicorn  fastapi  python-multipart
  • Create a function that accepts a file as input and reads it. This function, named read_file, processes the uploaded file. Schema using Strawberry, specifying the mutation. Ensure to override the default scalar for file uploads to utilize the provided Upload scalar. 

crud.py 

				
					from sqlalchemy.orm import Session 

import strawberry 

from typing import List, Union, Any, Callable 

from strawberry.file_uploads import Upload 

from starlette.datastructures import UploadFile 

@strawberry.type 

class Mutation:     

    @strawberry.mutation 

    async def read_file(self, file: Upload) -> str: 

        return (await file.read()).decode("utf-8") 

schema = strawberry.Schema(query=Query,mutation=Mutation, scalar_overrides={UploadFile: Upload}) 
				
			

Create a FastAPI endpoint at “/GraphQL” to handle GraphQL mutations. Use add_route to integrate the GraphQL functionality provided by Strawberry into your FastAPI application. 

main.py 

				
					from fastapi import FastAPI 

from strawberry.asgi import GraphQL 

from crud import schema 

app = FastAPI() 

GraphQL_app = GraphQL(schema) 

# Add GraphQL routes to FastAPI app 

app.add_route("/GraphQL", GraphQL_app) 
				
			
  • Execute the command uvicorn main:app –reload to  run   the application. After running, access it at http://localhost:8000/GraphQL.

You can also make API calls using Postman.
 
To upload a file using Postman, follow these steps: 

  • Set up the request as a POST request to the GraphQL endpoint.
  • In the request body, select “form-data”.
  • Add the following key-value pairs in the form-data: 
    1. Key: operations  
          Value:  

      “query”: “mutation($file: Upload!){ readFile(file: $file) }”, 
      “variables”: { “file”: null } 

           2. Key: map  
               Value: 
    { “file”: [“variables.file”] } 

       3.  Key: file  
          Value: Select the file you want to upload using the file selector. 

    This setup allows you to upload a file via the file parameter. 

Here’s a screenshot from Postman showing the testing of reading file data by upload a file using GraphQL.

GraphQL

In conclusion, GraphQL makes CRUD operations easier by putting them all in one place through queries and mutations. This makes it easier for developers to build APIs and for clients to get exactly the data they need, making apps faster. But GraphQL faces challenges like query complexity, where really deep queries can slow down servers. Also, caching and setting limits on requests can be tricky, which affects how well servers run. 

Table of Contents

Have Any Project

or Work Together?

          Success!!

          Keep an eye on your inbox for the PDF, it's on its way!

          If you don't see it in your inbox, don't forget to give your junk folder a quick peek. Just in case.



              You have successfully subscribed to the newsletter

              There was an error while trying to send your request. Please try again.

              Zehntech will use the information you provide on this form to be in touch with you and to provide updates and marketing.