Organización Backend

Estructura de carpetas y convenciones para proyectos Django, FastAPI y NestJS.

Proyectos backend — Estándares de organización para Django, FastAPI y NestJS

Propósito

Esta guía define la estructura de carpetas y convenciones que deben seguir los proyectos backend del DTI. El objetivo es garantizar consistencia y facilitar el mantenimiento.

FastAPI

Estructura de carpetas

proyecto/
├── app/
│   ├── api/
│   │   ├── users/
│   │   │   ├── __init__.py
│   │   │   ├── routes.py
│   │   │   ├── schemas.py
│   │   │   └── dependencies.py
│   │   └── __init__.py
│   ├── core/
│   │   ├── __init__.py
│   │   ├── config.py
│   │   ├── security.py
│   │   └── exceptions.py
│   ├── db/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── session.py
│   │   └── repositories/
│   ├── models/
│   │   ├── __init__.py
│   │   └── user.py
│   ├── schemas/
│   │   ├── __init__.py
│   │   └── user.py
│   ├── services/
│   │   ├── __init__.py
│   │   └── user_service.py
│   └── main.py
├── tests/
│   ├── __init__.py
│   ├── conftest.py
│   ├── api/
│   └── unit/
├── alembic/
│   ├── versions/
│   └── env.py
├── requirements.txt
├── .env.example
└── README.md

Ejemplo de router

# app/api/users/routes.py
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.db.session import get_db
from app.schemas.user import UserCreate, UserResponse
from app.services.user_service import UserService

router = APIRouter(prefix="/users", tags=["users"])

@router.post("/", response_model=UserResponse, status_code=201)
def create_user(user: UserCreate, db: Session = Depends(get_db)):
    service = UserService(db)
    return service.create(user)

Django

Estructura de carpetas

proyecto/
├── project/
│   ├── __init__.py
│   ├── settings/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── development.py
│   │   └── production.py
│   ├── urls.py
│   ├── wsgi.py
│   └── asgi.py
├── apps/
│   ├── core/
│   │   ├── __init__.py
│   │   ├── models.py
│   │   ├── views.py
│   │   ├── serializers.py
│   │   └── urls.py
│   └── users/
│       ├── __init__.py
│       ├── models.py
│       ├── views.py
│       ├── serializers.py
│       └── urls.py
├── tests/
├── requirements.txt
├── manage.py
└── README.md

Ejemplo de app Django

# apps/users/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    email = models.EmailField(unique=True)
    role = models.CharField(max_length=20, default="viewer")
    created_at = models.DateTimeField(auto_now_add=True)

NestJS

Estructura de carpetas

proyecto/
├── src/
│   ├── modules/
│   │   ├── users/
│   │   │   ├── users.module.ts
│   │   │   ├── users.controller.ts
│   │   │   ├── users.service.ts
│   │   │   ├── dto/
│   │   │   │   ├── create-user.dto.ts
│   │   │   │   └── update-user.dto.ts
│   │   │   └── entities/
│   │   │       └── user.entity.ts
│   │   └── auth/
│   ├── common/
│   │   ├── decorators/
│   │   ├── guards/
│   │   ├── filters/
│   │   └── interceptors/
│   ├── config/
│   │   └── configuration.ts
│   └── main.ts
├── test/
├── package.json
└── tsconfig.json

Ejemplo de módulo

// src/modules/users/users.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './entities/user.entity';
import { CreateUserDto } from './dto/create-user.dto';

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
  ) {}

  async create(dto: CreateUserDto): Promise<User> {
    const user = this.usersRepository.create(dto);
    return this.usersRepository.save(user);
  }
}

Convenciones de naming

TipoConvenciónEjemplo
Archivoskebab-caseuser-service.ts, auth-middleware.py
ClasesPascalCaseUserService, AuthMiddleware
VariablescamelCasegetUserById, isAuthenticated
FuncionescamelCasecreateUser(), validateToken()
ConstantesUPPER_SNAKE_CASEMAX_RETRY_COUNT, API_BASE_URL
Bases de datossnake_caseuser_profile, course_enrollment

Imports

Usar imports absolutos desde la raíz del proyecto:

# ✓ Correcto
from app.services.user_service import UserService

# ✗ Incorrecto
from ../../services.user_service import UserService
// ✓ Correcto
import { UsersService } from '@modules/users/users.service';

// ✗ Incorrecto
import { UsersService } from '../users/users.service';

Siguiente paso

Revisar Organización de Proyectos Frontend para conocer la estructura de carpetas de interfaces web.

Referencias