Python FastAPI: Getting Started Guide

Okay, here’s a comprehensive article on getting started with Python FastAPI, aiming for approximately 5000 words:

Python FastAPI: A Comprehensive Getting Started Guide

FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints. It’s designed to be easy to use, fast to code with, and incredibly performant. It boasts automatic data validation, interactive documentation, and a focus on developer experience. This guide will walk you through everything you need to know to get started with FastAPI, from basic installation to deploying a production-ready API.

Table of Contents

  1. Introduction: Why FastAPI?
    • The Need for Speed and Simplicity
    • Key Features
    • Comparison with Flask and Django
  2. Installation and Setup
    • Prerequisites
    • Installing FastAPI and Uvicorn
    • Creating a Virtual Environment (Recommended)
    • Setting up Your Project Directory
  3. Your First FastAPI Application
    • Creating a Minimal main.py
    • Running the Application with Uvicorn
    • Understanding the Code
    • Interactive API Documentation (Swagger UI and ReDoc)
  4. Path Operations
    • Defining Path Parameters
    • Type Hints and Data Validation
    • Query Parameters
    • Request Body (Using Pydantic)
    • Combining Path, Query, and Request Body Parameters
  5. Data Validation and Modeling with Pydantic
    • Introduction to Pydantic
    • Defining Data Models
    • Field Types and Constraints
    • Nested Models
    • Automatic Data Conversion
    • Custom Validators
  6. Handling Errors
    • Default Error Handling
    • Raising HTTP Exceptions
    • Custom Exception Handlers
  7. Response Handling
    • Returning Different Response Types (JSON, HTML, Plain Text, etc.)
    • Setting Response Status Codes
    • Custom Headers
    • Response Models (Data Filtering and Transformation)
  8. Working with Databases
    • Choosing a Database (SQLite, PostgreSQL, MySQL, etc.)
    • Using SQLAlchemy (ORM)
    • Connecting to a Database
    • Defining Database Models
    • CRUD Operations (Create, Read, Update, Delete)
    • Database Migrations (Alembic)
  9. Dependency Injection
    • Understanding Dependency Injection
    • Creating Dependencies
    • Using Dependencies in Path Operations
    • Sub-Dependencies
    • Dependencies with yield (Context Managers)
  10. Background Tasks
    • Running Tasks in the Background
    • Using BackgroundTasks
    • When to Use Background Tasks
  11. Security
    • Authentication (OAuth2 with Password Flow)
    • Authorization (Roles and Permissions)
    • Protecting Against Common Web Vulnerabilities (CORS, CSRF)
    • HTTPS
  12. Testing
    • Writing Unit Tests with pytest
    • Testing Path Operations
    • Using TestClient
    • Mocking Dependencies
  13. Deployment
    • Choosing a Deployment Strategy (Docker, Cloud Providers, etc.)
    • Preparing for Production (Gunicorn)
    • Example: Deploying to Heroku
    • Example: Deploying with Docker
  14. Advanced Topics
    • Using WebSockets
    • Middleware
    • Customizing OpenAPI (Swagger UI)
    • Asynchronous Database Operations
    • Streaming Responses
    • Event Handling (Startup and Shutdown)
  15. Conclusion and Further Resources

1. Introduction: Why FastAPI?

In the world of web development with Python, frameworks like Flask and Django have long been the dominant players. Flask is known for its simplicity and flexibility, making it ideal for small to medium-sized projects. Django, on the other hand, is a full-featured framework with a “batteries-included” approach, suitable for large and complex applications. FastAPI enters this landscape as a modern alternative, combining the best aspects of both while introducing innovative features.

  • The Need for Speed and Simplicity:

    Modern web applications, especially APIs, demand high performance and rapid development cycles. Traditional frameworks often require significant boilerplate code and manual configuration. FastAPI addresses these concerns by leveraging Python’s type hints and asynchronous capabilities to provide both speed and simplicity.

  • Key Features:

    • Fast: Built on top of Starlette (for the web parts) and Pydantic (for the data parts), FastAPI is exceptionally fast, comparable to NodeJS and Go in terms of performance. This is largely due to its asynchronous nature, allowing it to handle many concurrent requests efficiently.
    • Fast to Code: FastAPI minimizes code duplication and boilerplate. Type hints drive automatic data validation, serialization, and documentation. This significantly speeds up development time.
    • Easy to Learn: The framework is designed to be intuitive and easy to learn, with a clear and concise API. The excellent documentation further aids in rapid onboarding.
    • Automatic Data Validation: Leveraging Pydantic, FastAPI automatically validates incoming data based on type hints. This prevents common errors and ensures data integrity.
    • Interactive API Documentation: FastAPI automatically generates interactive API documentation using OpenAPI (Swagger UI) and ReDoc. This makes it easy for developers to understand and interact with your API.
    • Dependency Injection: FastAPI has a powerful yet easy-to-use dependency injection system, promoting code reusability and testability.
    • Standards-Based: FastAPI is built on open standards like OpenAPI (formerly Swagger) and JSON Schema, ensuring compatibility and interoperability.
  • Comparison with Flask and Django:

    Feature FastAPI Flask Django
    Performance Very High Moderate Moderate
    Ease of Use Very Easy Easy Moderate
    Data Validation Automatic (Pydantic) Manual/Extensions ORM-based
    Documentation Automatic (OpenAPI) Manual/Extensions Manual/Extensions
    Dependency Inj. Built-in Extensions Limited
    Async Support Native Extensions ASGI Support (Recent)
    “Batteries” Minimal Minimal Full-Featured
    Best For APIs, Microservices Small/Medium Projects Large/Complex Projects

    FastAPI is a strong choice for building APIs and microservices where performance and development speed are critical. Flask remains a good option for smaller projects or when maximum flexibility is required. Django excels in building large, monolithic applications with many built-in features.

2. Installation and Setup

  • Prerequisites:

    • Python 3.7+: FastAPI requires Python 3.7 or higher. You can check your Python version by running python --version or python3 --version in your terminal.
    • pip: The Python package installer. It usually comes bundled with Python. Verify with pip --version or pip3 --version.
  • Installing FastAPI and Uvicorn:

    Open your terminal and run the following command:

    bash
    pip install fastapi uvicorn

    This installs both FastAPI and Uvicorn. Uvicorn is an ASGI (Asynchronous Server Gateway Interface) server, which is needed to run FastAPI applications. Think of it as the engine that handles incoming requests and serves your FastAPI application.

  • Creating a Virtual Environment (Recommended):

    It’s highly recommended to use a virtual environment to isolate your project’s dependencies. This prevents conflicts between different projects that might require different versions of the same package.

    “`bash

    Create a virtual environment (choose one)

    python3 -m venv .venv # Using the built-in venv module

    OR

    virtualenv .venv # Using the virtualenv package (if installed)

    Activate the virtual environment (different commands depending on your OS)

    On macOS and Linux:

    source .venv/bin/activate

    On Windows (cmd.exe):

    .venv\Scripts\activate.bat

    On Windows (PowerShell):

    .venv\Scripts\Activate.ps1
    “`

    Once the virtual environment is activated, your terminal prompt will usually change to indicate this (e.g., (.venv) $). Now, any packages you install with pip will be installed within this isolated environment. To deactivate the environment, simply run deactivate.

  • Setting up Your Project Directory:

    Create a new directory for your project:

    bash
    mkdir my_fastapi_project
    cd my_fastapi_project

    Inside this directory, you’ll create your Python files.

3. Your First FastAPI Application

  • Creating a Minimal main.py:

    Create a file named main.py inside your project directory with the following content:

    “`python
    from fastapi import FastAPI

    app = FastAPI()

    @app.get(“/”)
    async def root():
    return {“message”: “Hello World”}
    “`

  • Running the Application with Uvicorn:

    In your terminal, within your project directory and with your virtual environment activated, run the following command:

    bash
    uvicorn main:app --reload

    • uvicorn: Starts the Uvicorn server.
    • main: Refers to the main.py file.
    • app: Refers to the app = FastAPI() instance within main.py.
    • --reload: This is a development flag that tells Uvicorn to automatically restart the server whenever you make changes to your code. This is extremely helpful during development.

    You should see output similar to this:

    INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
    INFO: Started reloader process [12345] using statreload
    INFO: Started server process [67890]
    INFO: Waiting for application startup.
    INFO: Application startup complete.

  • Understanding the Code:

    • from fastapi import FastAPI: Imports the FastAPI class.
    • app = FastAPI(): Creates an instance of the FastAPI class. This is your main application object.
    • @app.get("/"): This is a path operation decorator. It tells FastAPI that the function below should handle requests to the root path (/) using the HTTP GET method.
    • async def root():: Defines an asynchronous function named root. The async keyword is crucial for FastAPI’s performance. It indicates that this function can run concurrently with other tasks.
    • return {"message": "Hello World"}: Returns a Python dictionary. FastAPI automatically converts this dictionary into a JSON response.
  • Interactive API Documentation (Swagger UI and ReDoc):

    One of the most compelling features of FastAPI is its automatic API documentation. Once your application is running, open your web browser and go to:

    • Swagger UI: http://127.0.0.1:8000/docs
    • ReDoc: http://127.0.0.1:8000/redoc

    Swagger UI provides an interactive interface where you can explore your API, see the available endpoints, their parameters, and even try them out directly in the browser. ReDoc offers a more traditional, read-only documentation view. These are generated automatically based on your code and type hints.

4. Path Operations

Path operations are the core of your API. They define the different endpoints that your API exposes and the HTTP methods they support.

  • Defining Path Parameters:

    Path parameters are parts of the URL that can vary. You define them using curly braces {} in the path.

    “`python
    from fastapi import FastAPI

    app = FastAPI()

    @app.get(“/items/{item_id}”)
    async def read_item(item_id: int):
    return {“item_id”: item_id}
    “`

    In this example, item_id is a path parameter. When you access /items/5, FastAPI will extract the value 5 and pass it to the read_item function as the item_id argument.

  • Type Hints and Data Validation:

    Notice the item_id: int in the function signature. This is a Python type hint. FastAPI uses these type hints to:

    1. Validate the data: If you try to access /items/abc, FastAPI will return an error because “abc” cannot be converted to an integer.
    2. Convert the data: FastAPI will automatically convert the string “5” from the URL into an integer 5.
    3. Provide documentation: The type hint is used to generate the API documentation.

    You can use various Python types, including str, float, bool, and even more complex types like datetime and custom Pydantic models (which we’ll cover later).

  • Query Parameters:

    Query parameters are optional parameters passed in the URL after a question mark (?). They are typically used for filtering, sorting, or pagination.

    “`python
    from fastapi import FastAPI

    app = FastAPI()

    @app.get(“/items/”)
    async def read_items(skip: int = 0, limit: int = 10):
    return {“skip”: skip, “limit”: limit}
    “`

    Here, skip and limit are query parameters. You can access them like this:

    • /items/ (uses default values: skip=0, limit=10)
    • /items/?skip=20&limit=5

    FastAPI handles default values, type conversion, and validation for query parameters just like it does for path parameters. You can also make query parameters required by omitting the default value:

    python
    @app.get("/items/")
    async def read_items(q: str): # 'q' is now a required query parameter
    return {"q": q}

  • Request Body (Using Pydantic):

    For operations that send data to the server (like creating or updating resources), you’ll typically use a request body. FastAPI uses Pydantic models to define the structure and validation of request bodies.

    “`python
    from fastapi import FastAPI
    from pydantic import BaseModel

    app = FastAPI()

    class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

    @app.post(“/items/”)
    async def create_item(item: Item):
    return item
    “`

    • class Item(BaseModel):: Defines a Pydantic model named Item. This model specifies the expected structure of the request body.
    • name: str: The name field is a required string.
    • description: str | None = None: The description field is an optional string (can be None). The = None provides a default value. The | None syntax (or Optional[str]) is used for optional fields.
    • price: float: The price field is a required float.
    • tax: float | None = None: The tax field is an optional float.
    • @app.post("/items/"): Uses the POST HTTP method, typically used for creating resources.
    • async def create_item(item: Item):: The item parameter is of type Item. FastAPI will automatically parse the request body (which should be JSON), validate it against the Item model, and pass a populated Item object to the function.

    To send a request to this endpoint, you would send a JSON payload like this:

    json
    {
    "name": "Foo",
    "description": "A very nice Item",
    "price": 50.2,
    "tax": 10.5
    }

    If any of the required fields are missing, or if the data types are incorrect, FastAPI will return a detailed error message.

  • Combining Path, Query, and Request Body Parameters:

    You can combine path parameters, query parameters, and a request body in a single path operation:
    python
    @app.put("/items/{item_id}") #PUT is often used for updating
    async def update_item(item_id: int, item: Item, q: str | None = None):
    result = {"item_id": item_id, **item.dict()} #converts Item instance to a dictionary
    if q:
    result.update({"q": q})
    return result

    This endpoint expects:

    • A path parameter item_id (an integer).
    • A request body that conforms to the Item model.
    • An optional query parameter q (a string).

5. Data Validation and Modeling with Pydantic

Pydantic is a data validation and parsing library that is deeply integrated with FastAPI. It’s the foundation for defining request bodies, response models, and other data structures.

  • Introduction to Pydantic:

    Pydantic allows you to define data models using Python type hints. It handles data validation, type coercion, and serialization/deserialization. It excels at converting raw data (like JSON) into well-defined Python objects and vice versa.

  • Defining Data Models:

    As we saw earlier, you create Pydantic models by subclassing BaseModel:

    “`python
    from pydantic import BaseModel

    class User(BaseModel):
    id: int
    name: str
    signup_ts: datetime | None = None
    friends: list[int] = []
    “`

  • Field Types and Constraints:

    Pydantic supports a wide range of field types, including:

    • Basic Types: int, float, str, bool, bytes
    • Date/Time Types: datetime, date, time, timedelta
    • Collection Types: list, tuple, dict, set, frozenset
    • Other Types: UUID, FilePath, DirectoryPath, EmailStr, UrlStr, and more.

    You can also add constraints to your fields:

    “`python
    from pydantic import BaseModel, Field

    class Item(BaseModel):
    name: str = Field(…, min_length=3, max_length=50) # Required, length between 3 and 50
    price: float = Field(…, gt=0) # Required, greater than 0
    description: str | None = Field(None, title=”The description of the item”, max_length=300)
    tax: float = 0.1 # Default value of 0.1
    ``
    *
    Field(…): The ellipsissignifies that the field is *required*.
    *
    min_length,max_length: String length constraints.
    *
    gt(greater than),lt(less than),ge(greater than or equal to),le(less than or equal to): Numeric constraints.
    *
    title,description`: Metadata that will be included in the generated OpenAPI documentation.
    You can explore the Pydantic documentation for a complete list of available field types and constraints.

  • Nested Models:

    You can create complex, nested data structures by using Pydantic models within other Pydantic models:

    “`python
    from pydantic import BaseModel

    class Image(BaseModel):
    url: str
    name: str

    class Item(BaseModel):
    name: str
    price: float
    image: Image | None = None # An optional Image
    “`

    This allows you to represent hierarchical data in a structured and validated way.

  • Automatic Data Conversion:

    Pydantic automatically converts data to the specified types when possible. For example, if you have a field defined as price: float and you receive "12.99" in the JSON, Pydantic will convert it to the float 12.99.

  • Custom Validators:

    For more complex validation logic, you can define custom validators using the @validator decorator:

    “`python
    from pydantic import BaseModel, validator

    class User(BaseModel):
    name: str
    age: int

    @validator("age")
    def age_must_be_positive(cls, value):
        if value <= 0:
            raise ValueError("Age must be positive")
        return value
    

    “`

    The @validator("age") decorator indicates that the age_must_be_positive function should be used to validate the age field. The validator function receives the field value as input and should either return the validated value or raise a ValueError if the validation fails.

6. Handling Errors

FastAPI provides robust error handling capabilities, automatically generating informative error responses for common scenarios.

  • Default Error Handling:

    When a request fails validation (e.g., a required field is missing or a type mismatch occurs), FastAPI automatically returns a JSON response with a 422 Unprocessable Entity status code and a detailed error message. For example:

    json
    {
    "detail": [
    {
    "loc": [
    "body",
    "name"
    ],
    "msg": "field required",
    "type": "value_error.missing"
    }
    ]
    }

    The detail field provides a list of errors, each with a loc (location), msg (message), and type (error type). This makes it easy for clients to understand what went wrong.

  • Raising HTTP Exceptions:

    You can manually raise HTTP exceptions within your path operations to return specific error responses. FastAPI provides the HTTPException class for this purpose:

    “`python
    from fastapi import FastAPI, HTTPException

    app = FastAPI()

    items = {“foo”: “The Foo Wrestlers”}

    @app.get(“/items/{item_id}”)
    async def read_item(item_id: str):
    if item_id not in items:
    raise HTTPException(status_code=404, detail=”Item not found”)
    return {“item”: items[item_id]}
    “`

    • raise HTTPException(status_code=404, detail="Item not found"): Raises an HTTPException with a 404 Not Found status code and a custom detail message. FastAPI will catch this exception and return an appropriate JSON response.

    You can use any valid HTTP status code (e.g., 400 Bad Request, 401 Unauthorized, 403 Forbidden, 500 Internal Server Error).

  • Custom Exception Handlers:

    For more fine-grained control over error handling, you can define custom exception handlers. These handlers are functions that are called when a specific exception is raised.

    “`python
    from fastapi import FastAPI, Request
    from fastapi.responses import JSONResponse
    from fastapi.exceptions import RequestValidationError

    app = FastAPI()

    @app.exception_handler(RequestValidationError)
    async def validation_exception_handler(request: Request, exc: RequestValidationError):
    return JSONResponse(
    status_code=400, # Changed status code to 400
    content={“message”: “Validation failed”, “errors”: exc.errors()},
    )

    @app.post(“/items/”)
    async def create_item(name: str): # No Pydantic model for demonstration
    return {“name”: name}
    “`

    • @app.exception_handler(RequestValidationError): Registers a handler for RequestValidationError, which is the exception raised by FastAPI for validation errors.
    • async def validation_exception_handler(request: Request, exc: RequestValidationError):: The handler function receives the Request object and the exception instance (exc).
    • return JSONResponse(...): Returns a custom JSON response. In this case, we’re changing the status code to 400 Bad Request and providing a more user-friendly message.

    You can create custom exception handlers for any exception type, including your own custom exceptions.

7. Response Handling

FastAPI provides flexibility in how you return responses from your path operations.

  • Returning Different Response Types:

    • JSON (Default): If you return a Python dictionary, list, or a Pydantic model, FastAPI automatically converts it to a JSON response.
    • HTML: You can return a string containing HTML, and FastAPI will set the Content-Type header to text/html.
      “`python
      from fastapi import FastAPI
      from fastapi.responses import HTMLResponse

      app = FastAPI()
      @app.get(“/html”, response_class=HTMLResponse)
      async def get_html():
      return “””


      Some HTML in here

      Look ma! HTML!



      “””
      ``
      * **Plain Text:** You can return a plain string, and FastAPI will set the
      Content-Typetotext/plain`.

      “`python
      from fastapi import FastAPI
      from fastapi.responses import PlainTextResponse

      app = FastAPI()
      @app.get(“/plain-text”, response_class=PlainTextResponse)
      async def get_plain_text():
      return “This is plain text.”
      “`

    • Other Response Types: FastAPI provides specific response classes for various content types, including FileResponse, StreamingResponse, RedirectResponse, etc.

  • Setting Response Status Codes:

    You can explicitly set the response status code using the status_code parameter in the path operation decorator:

    python
    @app.post("/items/", status_code=201) # 201 Created
    async def create_item(item: Item):
    return item

  • Custom Headers:

    You can set custom response headers using the response object:

    “`python
    from fastapi import FastAPI, Response

    app = FastAPI()

    @app.get(“/items/”)
    async def read_items(response: Response):
    response.headers[“X-Custom-Header”] = “My Custom Value”
    return {“message”: “Items”}
    “`

  • Response Models (Data Filtering and Transformation):

    You can use Pydantic models as response models to filter and transform the data returned by your API. This is useful for:

    • Hiding sensitive information: You might not want to expose all fields of a database model to the client.
    • Formatting data: You can change the format of data (e.g., converting a datetime object to a specific string format).
    • Adding computed fields: You can add fields that are calculated based on other fields.

    “`python
    from fastapi import FastAPI
    from pydantic import BaseModel

    app = FastAPI()

    class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

    class ItemOut(BaseModel): # Response model
    name: str
    price: float

    @app.get(“/items/{item_id}”, response_model=ItemOut)
    async def read_item(item_id: int):
    # Simulate fetching an item from a database
    item = Item(name=”Foo”, description=”A very nice Item”, price=50.2, tax=10.5)
    return item
    “`

    • response_model=ItemOut: Specifies that the response should be validated and serialized according to the ItemOut model. Only the name and price fields will be included in the response, even though the item object has other fields.

    You can also use response_model with a list of models, for instance:

    python
    @app.get("/items/", response_model=list[ItemOut])
    async def read_items():
    # Simulate fetching a list of items from a database
    items = [
    Item(name="Foo", price=50.2),
    Item(name="Bar", price=25.1),
    ]
    return items

8. Working with Databases

Most real-world APIs interact with a database to store and retrieve data. FastAPI doesn’t have a built-in database layer, but it integrates seamlessly with popular database tools like SQLAlchemy (an ORM) and other database drivers.

  • Choosing a Database:

    FastAPI is compatible with various databases, including:

    • SQLite: A lightweight, file-based database. Good for development and small projects.
    • PostgreSQL: A powerful, open-source relational database. A popular choice for production applications.
    • MySQL: Another popular open-source relational database.
    • MongoDB: A NoSQL document database.

    The choice of database depends on your project’s requirements.

  • Using SQLAlchemy (ORM):

    SQLAlchemy is a popular Object-Relational Mapper (ORM) for Python. It allows you to interact with databases using Python objects instead of writing raw SQL queries. This makes your code more readable, maintainable, and less prone to SQL injection vulnerabilities.
    We install SQLAlchemy with:

    bash
    pip install sqlalchemy

  • Connecting to a Database:

    Here’s an example of connecting to a SQLite database using SQLAlchemy:

    “`python
    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker

    SQLALCHEMY_DATABASE_URL = “sqlite:///./sql_app.db” # SQLite database file

    engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={“check_same_thread”: False}
    ) # connect_args only needed for SQLite
    SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

    Base = declarative_base()
    ``
    *
    SQLALCHEMY_DATABASE_URL: Defines the database connection string. For SQLite, it's the path to the database file. For other databases, you'll need to provide the appropriate connection details (username, password, host, port, database name).
    *
    create_engine(…): Creates a SQLAlchemy engine, which is responsible for connecting to the database.
    *
    SessionLocal = sessionmaker(…): Creates a session factory. You'll use this to create individual database sessions.
    *
    Base = declarative_base()`: Creates a base class for your declarative models.

  • Defining Database Models:

    You define your database tables as Python classes that inherit from Base:

    “`python
    from sqlalchemy import Boolean, Column, Integer, String
    from sqlalchemy.orm import relationship
    from .database import Base # we import Base from our database.py file

    class Item(Base):
    tablename = “items”

    id = Column(Integer, primary_key=True, index=True)
    title = Column(String, index=True)
    description = Column(String, index=True)
    is_active = Column(Boolean, default=True)
    

    “`

    • __tablename__: Specifies the name of the database table.
    • Column(...): Defines the columns of the table, including their data types and constraints (e.g., primary_key, index).
  • CRUD Operations (Create, Read, Update, Delete):

    Here’s how you perform CRUD operations using SQLAlchemy and FastAPI:
    “`python
    from fastapi import FastAPI, Depends, HTTPException
    from sqlalchemy.orm import Session
    from . import crud, models, schemas # our supporting files
    from .database import SessionLocal, engine

    models.Base.metadata.create_all(bind=engine) # Creates the tables in the database

    app = FastAPI()

    Dependency

    def get_db():
    db = SessionLocal()
    try:
    yield db
    finally:
    db.close()

    @app.post(“/items/”, response_model=schemas.Item) #schemas.Item is a Pydantic model
    def create_item(item: schemas.ItemCreate, db: Session = Depends(get_db)): # schemas.ItemCreate is another Pydantic model
    db_item = crud.create_item(db=db, item=item) # we create a new item
    return db_item

    @app.get(“/items/”, response_model=list[schemas.Item])
    def read_items(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    items = crud.get_items(db, skip=skip, limit=limit)
    return items

    @app.get(“/items/{item_id}”, response_model=schemas.Item)
    def read_item(item_id: int, db: Session = Depends(get_db)):
    db_item = crud.get_item(db, item_id=item_id)
    if db_item is None:
    raise HTTPException(status_code=404, detail=”Item not found”)
    return db_item

    @app.put(“/items/{item_id}”, response_model=schemas.Item)
    def update_item(item_id: int, item_update: schemas.ItemUpdate, db: Session = Depends(get_db)):
    db_item = crud.get_item(db, item_id)
    if db_item is None:
    raise HTTPException(status_code=404, detail=”Item not found”)

        updated_item = crud.update_item(db, db_item, item_update)
        return updated_item
    

    @app.delete(“/items/{item_id}”)
    def delete_item(item_id: int, db: Session = Depends(get_db)):
    db_item = crud.get_item(db, item_id)
    if db_item is None:
    raise HTTPException(status_code=404, detail=”Item not found”)
    crud.delete_item(db, db_item)
    return {“message”: “Item deleted”}

    We place our CRUD functions in `crud.py`:python
    # crud.py
    from sqlalchemy.orm import Session
    from . import models, schemas

    def get_item(db: Session, item_id: int):
    return db.query(models.Item).filter(models.Item.id == item_id).first()

    def get_items(db: Session, skip: int = 0, limit: int = 100):
    return db.query(models.Item).offset(skip).limit(limit).all()

    def create_

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top