Skip to content

Project Layout

Single-App Architecture

SpeedPy uses a single-app architecture with two Django apps:

  • mainapp — Primary application containing all business logic (models, views, forms, tasks)
  • usermodel — Dedicated app for the custom User model with email-based authentication

There is also a utility app:

  • speedpycom — Contains management commands and the BaseModel abstract model

Directory Structure

myproject/
├── project/                 # Django project settings
│   ├── settings.py          # All configuration
│   ├── urls.py              # Root URL routing
│   ├── celeryapp.py         # Celery configuration
│   ├── wsgi.py
│   └── context_processors.py
├── mainapp/                 # Primary business logic app
│   ├── models/              # Models (one file per domain)
│   │   ├── __init__.py      # Imports & __all__
│   │   ├── teams.py         # Team, TeamMembership, TeamInvitation
│   │   └── otp_profile.py   # OTP profile model
│   ├── views/               # Views (one file per feature)
│   │   ├── __init__.py
│   │   ├── dashboard.py
│   │   ├── teams.py
│   │   ├── team_members.py
│   │   ├── otp_views.py
│   │   └── welcome.py
│   ├── forms/               # Forms (one file per feature)
│   ├── tasks/               # Celery tasks
│   │   ├── __init__.py
│   │   └── teams.py
│   ├── urls.py              # App-level URL routing
│   └── subscription_plans.py
├── usermodel/               # Custom User app
│   ├── models.py            # User model
│   ├── managers.py          # UserManager
│   ├── forms.py             # Auth forms (signup, login, etc.)
│   ├── adapters.py          # Allauth adapter with OTP support
│   └── views.py
├── speedpycom/              # Utility app
│   ├── models/
│   │   └── base.py          # BaseModel (UUID + timestamps)
│   └── management/commands/
├── templates/               # All templates (organized by app)
│   ├── emails/              # Email templates
│   └── ...
├── static/                  # Static files
│   └── mainapp/
│       ├── input.css        # Tailwind source CSS
│       └── styles.css       # Compiled Tailwind output
├── docker-compose.yml
├── Dockerfile
├── Makefile
├── pyproject.toml
├── uv.lock
├── package.json
├── tailwind.config.js
├── release.sh               # Deployment release script
├── .docker.env              # Docker environment template
└── manage.py

Key Patterns

Package-Style Organization

Models, views, and forms are organized as Python packages (directories with __init__.py) rather than single files. Each domain or feature gets its own file:

# mainapp/models/__init__.py
from .teams import Team, TeamMembership, TeamInvitation

__all__ = ["Team", "TeamMembership", "TeamInvitation"]

BaseModel

All application models should inherit from BaseModel, which provides:

  • UUID primary keyid = UUIDField(primary_key=True, default=uuid.uuid4)
  • Timestampscreated_at (auto_now_add) and updated_at (auto_now)
from speedpycom.models import BaseModel

class MyModel(BaseModel):
    name = models.CharField(max_length=255)

    class Meta:
        verbose_name = "My Model"

TeamModel

For multi-tenant models scoped to a team, inherit from TeamModel:

from mainapp.models.teams import TeamModel

class Project(TeamModel):
    name = models.CharField(max_length=255)
    # Automatically has: id, created_at, updated_at, team (FK)

Foreign Key References

Use string notation for foreign keys to avoid circular imports:

team = models.ForeignKey('mainapp.Team', on_delete=models.CASCADE)