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 theBaseModelabstract 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
├── requirements.txt
├── 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 key —
id = UUIDField(primary_key=True, default=uuid.uuid4) - Timestamps —
created_at(auto_now_add) andupdated_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)