基于FastAPI-Users实现用户管理系统的完整方案

FastAPI-Users是一个用于用户身份管理的扩展。它简化了用户注册、登录和权限管理的流程,用户只需初始化FastAPIUsers并包含路由即可。适用于需要完整用户管理系统(注册/登录/权限)的场景。

依赖下载

Python 3.9.21

pip install fastapi uvicorn

pip install pydantic

pip install aiosqlite

pip install fastapi-users

pip install fastapi-users[sqlalchemy] python-jose[cryptography]

pip install pyjwt

pip install passlib

pip install bcrypt

代码说明

目录结构

Main.py

import uuid

from fastapi import FastAPI, HTTPException, status, Depends, Query

from fastapi.responses import JSONResponse

from fastapi.middleware.cors import CORSMiddleware



"""

Import our tools

This is the database connection file

"""

from db import engine

from config import settings



from models.users import User, UserCreate, UserRead, UserUpdate, auth_backend, current_active_user, fastapi_users



app = FastAPI(

    title=settings.PROJECT_NAME,

    version=settings.PROJECT_VERSION

)



"""

Setup our origins...

...for now it's just our local environments

"""

origins = [

    "http://localhost:5173"

]



"""

Add the CORS middleware, it will pass the proper CORS headers

- https://fastapi.tiangolo.com/tutorial/middleware/

- https://fastapi.tiangolo.com/tutorial/cors/

"""

app.add_middleware(

    CORSMiddleware,

    allow_origins=origins,

    allow_credentials=True,

    allow_methods=["*"],

    allow_headers=["*"],

)





"""

FastAPI Users is going to give us all of our auth routes,

The `prefix` is the url that will precede each url.



These settings will generate these routes:

- auth/register

- auth/login

- auth/logout

"""

app.include_router(

    fastapi_users.get_auth_router(auth_backend),

    prefix="/auth",

    tags=["auth"],

)



app.include_router(

    fastapi_users.get_register_router(UserRead, UserCreate),

    prefix="/auth",

    tags=["auth"],

)



"""

We now return you to your regular routes.

"""

@app.get("/")

def home():

    return {"message": "Root Route"}





"""

This is a demo protected route, it will only

return the response if a user is authenticated.

"""

@app.get("/authenticated-route-demo")

async def authenticated_route(user: User = Depends(current_active_user)):

    return {"message": f"Hello {user.email}!"}

Db_connect.py

from sqlalchemy import create_engine

from sqlalchemy.engine import URL

from sqlalchemy.orm import sessionmaker





url = URL.create(

    drivername="",

    username="",

    password="",

    host="localhost",

    database="",

    port=5432

)



engine = create_engine(url)

Session = sessionmaker(bind=engine)

session = Session()

Db.py

from collections.abc import AsyncGenerator



from fastapi import Depends

from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase

from fastapi_users_db_sqlalchemy.access_token import (

    SQLAlchemyAccessTokenDatabase,

    SQLAlchemyBaseAccessTokenTableUUID,

)

from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine

from sqlalchemy.orm import DeclarativeBase

from config import settings



DATABASE_URL = f"sqlite+aiosqlite:///example.db"



class Base(DeclarativeBase):

    pass





class User(SQLAlchemyBaseUserTableUUID, Base):

    pass





class AccessToken(SQLAlchemyBaseAccessTokenTableUUID, Base):

    pass





engine = create_async_engine(DATABASE_URL)

async_session_maker = async_sessionmaker(engine, expire_on_commit=False)



async def create_db_and_tables():

    async with engine.begin() as conn:

        await conn.run_sync(Base.metadata.create_all)





async def get_async_session() -> AsyncGenerator[AsyncSession, None]:

    async with async_session_maker() as session:

        yield session





async def get_user_db(session: AsyncSession = Depends(get_async_session)):

    yield SQLAlchemyUserDatabase(session, User)





async def get_access_token_db(

    session: AsyncSession = Depends(get_async_session),

):

yield SQLAlchemyAccessTokenDatabase(session, AccessToken)

Config.py

from fastapi import HTTPException, status

import os

import sys

import base64

import json

from dotenv import load_dotenv



from pathlib import Path

env_path = Path('.') / '.env'

load_dotenv(dotenv_path=env_path)





def decode(variable):

    """Decodes a Platform.sh environment variable.

    Args:

        variable (string):

            Base64-encoded JSON (the content of an environment variable).

    Returns:

        An dict (if representing a JSON object), or a scalar type.

    Raises:

        JSON decoding error.



    Taken from:

    https://github.com/platformsh-templates/django4/blob/master/myapp/settings.py

    """

    try:

        if sys.version_info[1] > 5:

            return json.loads(base64.b64decode(variable))

        else:

            return json.loads(base64.b64decode(variable).decode('utf-8'))

    except json.decoder.JSONDecodeError:

        print('Error decoding JSON, code %d', json.decoder.JSONDecodeError)











class Settings:

    PROJECT_NAME: str = "FastAPI Users Test"

    PROJECT_VERSION: str = "1.0.0"

    PLATFORMSH_DB_RELATIONSHIP = 'postgresqldatabase'



    # Import some Platform.sh settings from the environment.

    if (os.getenv('PLATFORM_APPLICATION_NAME') is not None):

        DEBUG = False

        if (os.getenv('PLATFORM_APP_DIR') is not None):

            STATIC_ROOT = os.path.join(os.getenv('PLATFORM_APP_DIR'), 'static')

            if (os.getenv('PLATFORM_PROJECT_ENTROPY') is not None):

                SECRET_KEY = os.getenv('PLATFORM_PROJECT_ENTROPY')

                # Database service configuration, post-build only.

                if (os.getenv('PLATFORM_ENVIRONMENT') is not None):

                # Using Platform.sh

                    platform_relationships = decode(os.environ.get("PLATFORM_RELATIONSHIPS", "{}"))

                    db_settings = platform_relationships[PLATFORMSH_DB_RELATIONSHIP][0]



                    POSTGRES_HOST = db_settings["host"]

                    POSTGRES_PORT = db_settings["port"]

                    POSTGRES_USER = db_settings["username"]

                    POSTGRES_PASSWORD = db_settings['password']

                    POSTGRES_DB = db_settings['path']

    else:

        POSTGRES_USER: str = os.getenv("POSTGRES_USER")

        POSTGRES_PASSWORD = os.getenv("POSTGRES_PASSWORD")

        POSTGRES_HOST: str = os.getenv("POSTGRES_SERVER", "localhost")

        POSTGRES_PORT: str = os.getenv("POSTGRES_PORT", 5432)

        POSTGRES_DB: str = os.getenv("POSTGRES_DB", "tdd")

        SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"



    ALGORITHM = "HS256"

    DATABASE_URL = f"sqlite+aiosqlite:///example.db"







settings = Settings()

Users.py

import uuid

from typing import Optional

from fastapi import Depends, Request

from fastapi_users import FastAPIUsers, schemas, BaseUserManager, UUIDIDMixin

from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase

from fastapi_users.authentication import (

    AuthenticationBackend,

    BearerTransport,

    JWTStrategy,

)

from fastapi_users_db_sqlalchemy.access_token import (

    SQLAlchemyAccessTokenDatabase,

    SQLAlchemyBaseAccessTokenTableUUID,

)

from sqlalchemy.ext.asyncio import AsyncSession

from sqlalchemy.orm import DeclarativeBase



from config import settings

from db import get_async_session



bearer_transport = BearerTransport(tokenUrl="/auth/login")



class Base(DeclarativeBase):

    pass



class User(SQLAlchemyBaseUserTableUUID, Base):

    pass





class UserRead(schemas.BaseUser[uuid.UUID]):

    pass





class UserCreate(schemas.BaseUserCreate):

    pass





class UserUpdate(schemas.BaseUserUpdate):

    pass





class UserManager(UUIDIDMixin, BaseUserManager[User, uuid.UUID]):

    reset_password_token_secret = settings.SECRET_KEY

    verification_token_secret = settings.SECRET_KEY



    async def on_after_register(self, user: User, request: Optional[Request] = None):

        print(f"User {user.id} has registered.")



    async def on_after_forgot_password(

        self, user: User, token: str, request: Optional[Request] = None

    ):

        print(f"User {user.id} has forgot their password. Reset token: {token}")



    async def on_after_request_verify(

        self, user: User, token: str, request: Optional[Request] = None

    ):

        print(

            f"Verification requested for user {user.id}. Verification token: {token}")





class AccessToken(SQLAlchemyBaseAccessTokenTableUUID, Base):

    pass





"""

I'm including the following items here and importing them into main.py

- The docs put the schemas in their own file

- The docs put the get_user_db into the db.py file

"""



async def get_user_db(session: AsyncSession = Depends(get_async_session)):

    yield SQLAlchemyUserDatabase(session, User)





async def get_user_manager(user_db=Depends(get_user_db)):

    yield UserManager(user_db)





async def get_access_token_db(

    session: AsyncSession = Depends(get_async_session),

):

    yield SQLAlchemyAccessTokenDatabase(session, AccessToken)



"""

This sets up our JWT for each login.

FastAPI Users takes care of managing these for us,

including disabling on logout.

"""





def get_jwt_strategy() -> JWTStrategy:

    return JWTStrategy(secret=settings.SECRET_KEY, lifetime_seconds=3600)





auth_backend = AuthenticationBackend(

    name="jwt",

    transport=bearer_transport,

    get_strategy=get_jwt_strategy,

)



fastapi_users = FastAPIUsers[User, uuid.UUID](get_user_manager, [auth_backend])

current_active_user = fastapi_users.current_user(active=True)

启动命令

uvicorn main:app --reload

接口地址

http://127.0.0.1:8000/docs#

测试用例

不需要带认证的接口调用,调用后返回200,可以正常使用

需要带认证的接口返回401,没有认证成功

调用注册接口,注册账号

{

  "email": "admin@qq.com",

  "password": "admin",

  "is_active": true,

  "is_superuser": false,

  "is_verified": false

}

注册成功回执

表里的数据

调用登录接口,然后再次执行需要认证接口

源码地址

基于FastAPI-Users实现用户管理系统的例子资源-CSDN文库

<think>好的,我现在需要回答用户关于FastAPI和Django优劣比较的问题,以及FastAPI是否有类似Django的内置后台管理系统,还有FastAPI是否支持类似Django ORM的语法。首先,我得回顾用户之前的提问和我的回答,确保信息的一致性。 用户提到他们之前询问过Python库中类似Django ORM语法的选项,我之前推荐了Peewee、SQLAlchemy、Tortoise ORM等。现在他们想比较FastAPI和Django,并询问FastAPI是否有后台管理系统。我需要结合之前的引用内容,尤其是引用[1]、[4]、[5]中关于性能、框架特点的信息,以及引用[2]、[3]提到的Tortoise ORM和Djongo等内容。 首先,比较FastAPI和Django的优劣。根据引用[1],Django由于内置功能多,可能在性能上不如FastAPI,尤其是在高并发场景下。引用[4]的基准测试显示FastAPI的响应时间和吞吐量明显优于Django。而引用[5]提到FastAPI适合API和微服务,但功能相对单一,不如Django全面。Django的稳定性、内置功能(如ORM、Admin后台)是优势,但性能较低。FastAPI的优势是高性能和异步支持,但缺乏内置的管理界面,需要第三方库或自行开发。 接下来,关于FastAPI是否有内置后台管理。Django有内置的Admin,但FastAPI没有。根据用户引用[2],Tortoise ORM语法类似Django ORM,可能可以结合使用,但后台管理需要其他工具,比如admin interfaces或第三方库如FastAPI-Admin。 然后,类似Django ORM的语法,用户之前的问题已经涉及,这里需要再次确认。根据引用[2],Tortoise ORM语法接近Django ORM,适合在FastAPI中使用。此外,SQLAlchemy ORM和Peewee也是选项,但用户可能更关心与FastAPI兼容的解决方案。 在整理回答时,需要结构清晰,分点比较FastAPI和Django的优缺点,明确回答是否有后台管理,并推荐适用的ORM。同时,确保引用正确的引用标记,如引用[4]提到FastAPI性能数据,引用[2]关于Tortoise ORM的相似性。 还需要注意用户可能的需求:如果用户需要快速开发全栈应用,Django更合适;如果追求高性能API,FastAPI更好,但需额外处理后台管理。同时,确保回答中的建议基于引用内容,如引用[3]提到的Djongo适配器,但可能不在当前问题范围内。 最后,生成相关问题,可能需要围绕性能对比、如何扩展FastAPI功能、推荐的ORM选择等。</think>--- ### **FastAPI vs Django 对比分析** #### **1. 核心差异与适用场景** | **特性** | **Django** | **FastAPI** | |-------------------------|------------------------------------|--------------------------------------| | **框架定位** | 全栈Web框架(自带ORM、Admin、模板等) | 专注高性能API开发(微服务、RESTful API) | | **性能** | 较低(同步处理,基准测试约3,500 QPS)[^4] | 极高(异步处理,基准测试约14,000 QPS)[^4] | | **学习曲线** | 较高(需掌握全套生态) | 较低(基于Python类型提示,代码简洁) | | **内置功能** | 后台管理、ORM、用户认证、模板引擎等 | 无内置管理界面,需依赖第三方扩展 | | **异步支持** | 有限(Django 3.1+部分支持) | 原生异步支持(请求处理、数据库操作) | | **典型应用** | 内容管理系统、企业级Web应用 | 高性能API、实时数据处理、微服务架构 | --- #### **2. FastAPI 是否有内置后台管理?** **明确回答**:**无内置后台管理功能**,需通过以下方式实现类似功能: - **方案1:集成第三方库** 使用 `FastAPI-Admin` 或 `SQLAdmin` 构建管理界面(需结合ORM如SQLAlchemy或Tortoise ORM): ```python from fastapi_admin.app import app as admin_app from fastapi_admin.providers.login import UsernamePasswordProvider admin_app.add_provider(UsernamePasswordProvider) ``` - **方案2:自定义开发** 通过前端框架(React/Vue) + FastAPI接口自行实现管理后台。 - **方案3:混合架构** 使用Django Admin单独管理数据,通过FastAPI提供API服务[^3]。 --- #### **3. FastAPI 如何实现类似Django ORM的语法?** **推荐方案**: - **Tortoise ORM**(最接近Django语法) ```python from tortoise import fields, models class Product(models.Model): id = fields.IntField(pk=True) name = fields.CharField(max_length=100) # 查询示例 products = await Product.filter(name__contains="Book") # 类似Django的filter() ``` - 优势:支持异步、模型定义与查询语法高度相似[^2] - **SQLAlchemy ORM**(功能更强大) ```python from sqlalchemy import Column, Integer, String from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) name = Column(String(50)) ``` --- ### **4. 选择建议** - **选 Django 的场景**: - 需要快速构建全功能Web应用(含后台管理) - 依赖内置功能(用户认证、表单验证、ORM等) - 项目复杂度高,需长期维护(社区支持完善)[^1] - **选 FastAPI 的场景**: - 开发高性能API或微服务(如实时数据处理) - 需要异步支持提升并发能力 - 偏好代码简洁性和类型提示[^5] --- ### **5. 性能优化与扩展** - **Django优化方向**: - 使用缓存(Redis/Memcached) - 结合Celery异步任务队列 - 部署时启用ASGI服务器(Daphne/Uvicorn)[^4] - **FastAPI扩展方向**: - 集成Tortoise ORM或SQLAlchemy进行数据操作 - 使用 `FastAPI-Users` 实现用户认证 - 结合前端框架(Next.js/Nuxt.js)构建完整应用 --- ### **相关问题** 1. 如何为FastAPI添加用户认证功能? 2. Django项目如何迁移到FastAPI架构? 3. Tortoise ORM与SQLAlchemy在异步性能上的差异? 4. FastAPI如何实现实时通信(WebSocket)? --- 通过上述对比,您可以根据项目需求在 **开发效率**(Django)与 **性能扩展性**(FastAPI)之间做出选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码先觉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值