For full experience in demo - deposit, withdraw and check financial reports
Project Overview
A secure banking management system built with Django, featuring:
- Custom user authentication
- Account management
- Transaction processing
- Balance tracking
- Role-based access control
Technology Stack:
- Frontend: Django Templates
- Backend: Django 4.2
- Database: Supabase PostgreSQL
- Deployment: Vercel
- Auth: Django Allauth (Custom Implementation)
2. System Architecture

graph TD
A[Client] --> B[Vercel Edge Network]
B --> C[Django Application]
C --> D[Supabase Database]
C --> E[Redis Cache]
D --> F[(PostgreSQL Tables)]
C --> G[Static Files]
H[Admin User] --> C3. Authentication Flow
3.1 Custom User Model (accounts/models.py)
accounts/models.py
1from django.contrib.auth.models import AbstractUser
2from django.db import models
3
4class CustomUser(AbstractUser):
5 # Remove username field
6 username = None
7 email = models.EmailField(unique=True)
8
9 # Additional fields
10 phone_number = models.CharField(max_length=20)
11 date_of_birth = models.DateField()
12 is_verified = models.BooleanField(default=False)
13
14 USERNAME_FIELD = 'email'
15 REQUIRED_FIELDS = ['phone_number', 'date_of_birth']
16
17 def __str__(self):
18 return self.email3.2 Authentication Sequence Diagram

1sequenceDiagram
2 participant User
3 participant Frontend
4 participant Backend
5 participant Supabase
6
7 User->>Frontend: Access Login Page
8 Frontend->>Backend: GET /accounts/login/
9 Backend-->>Frontend: Login Form
10 User->>Frontend: Submit Credentials
11 Frontend->>Backend: POST /accounts/login/
12 Backend->>Supabase: Verify Credentials
13 Supabase-->>Backend: User Data
14 alt Valid Credentials
15 Backend->>Backend: Create Session
16 Backend-->>Frontend: Redirect to Dashboard
17 else Invalid Credentials
18 Backend-->>Frontend: Error Message
19 end3.3 Registration Process
- User Registration Endpoint:
accounts/views.py
# accounts/views.py
from django.views.generic import CreateView
from .forms import CustomUserCreationForm
class SignUpView(CreateView):
form_class = CustomUserCreationForm
success_url = reverse_lazy('login')
template_name = 'registration/signup.html'- Registration Steps:
/accounts/signup/
POST /accounts/signup/
Content-Type: application/x-www-form-urlencoded
email=user@example.com&
password1=securePassword123&
password2=securePassword123&
phone_number=+254712345678&
date_of_birth=1990-01-01- Verification Workflow:
- Email verification sent via Celery task
- Account activation required before login
- JWT token generation for API access
3.4 Password Management
Reset Flow:
accounts/urls.py
1# accounts/urls.py
2from django.urls import path
3from django.contrib.auth import views as auth_views
4
5urlpatterns = [
6 path('password_reset/', auth_views.PasswordResetView.as_view(
7 template_name='registration/password_reset.html',
8 email_template_name='registration/password_reset_email.html',
9 subject_template_name='registration/password_reset_subject.txt'
10 ), name='password_reset'),
11 path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(
12 template_name='registration/password_reset_done.html'
13 ), name='password_reset_done'),
14 path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(
15 template_name='registration/password_reset_confirm.html'
16 ), name='password_reset_confirm'),
17 path('reset/done/', auth_views.PasswordResetCompleteView.as_view(
18 template_name='registration/password_reset_complete.html'
19 ), name='password_reset_complete'),
20]4. Database Configuration
4.1 Supabase Connection
core/settings.py
1# core/settings.py
2DATABASES = {
3 'default': dj_database_url.config(
4 default=os.environ.get('DATABASE_URL'),
5 engine='django.db.backends.postgresql',
6 conn_max_age=600,
7 conn_health_checks=True,
8 ssl_require=True
9 )
10}4.2 Database Schema
1-- accounts_customuser
2CREATE TABLE accounts_customuser (
3 id SERIAL PRIMARY KEY,
4 password VARCHAR(128) NOT NULL,
5 last_login TIMESTAMP WITH TIME ZONE,
6 is_superuser BOOLEAN NOT NULL,
7 email VARCHAR(254) UNIQUE NOT NULL,
8 phone_number VARCHAR(20) NOT NULL,
9 date_of_birth DATE NOT NULL,
10 is_verified BOOLEAN NOT NULL,
11 ...
12);
13
14-- accounts_account
15CREATE TABLE accounts_account (
16 id SERIAL PRIMARY KEY,
17 account_type VARCHAR(20) NOT NULL,
18 account_number VARCHAR(20) UNIQUE NOT NULL,
19 balance NUMERIC(12,2) NOT NULL,
20 created_at TIMESTAMP WITH TIME ZONE NOT NULL,
21 user_id INTEGER REFERENCES accounts_customuser(id)
22);4.3 Database Schema Diagrams
Entity Relationship Diagram (ERD)

1classDiagram
2 class accounts_customuser {
3 +id: SERIAL (PK)
4 +password: VARCHAR(128)
5 +last_login: TIMESTAMPTZ
6 +is_superuser: BOOLEAN
7 +email: VARCHAR(254) UNIQUE
8 +phone_number: VARCHAR(20)
9 +date_of_birth: DATE
10 +is_verified: BOOLEAN
11 +created_at: TIMESTAMPTZ
12 +updated_at: TIMESTAMPTZ
13 }
14
15 class accounts_account {
16 +id: SERIAL (PK)
17 +account_type: VARCHAR(20)
18 +account_number: VARCHAR(20) UNIQUE
19 +balance: NUMERIC(12,2)
20 +created_at: TIMESTAMPTZ
21 +user_id: INT (FK → accounts_customuser)
22 }
23
24 class accounts_transaction {
25 +id: SERIAL (PK)
26 +transaction_type: VARCHAR(20)
27 +amount: NUMERIC(10,2)
28 +timestamp: TIMESTAMPTZ
29 +description: TEXT
30 +account_id: INT (FK → accounts_account)
31 }
32
33 accounts_customuser "1" --> "many" accounts_account : has
34 accounts_account "1" --> "many" accounts_transaction : contains4.4 Schema Relationships
- User → Account Relationship

flowchart LR
A[CustomUser] --> B[Account]
style A fill:#f9f,stroke:#333
style B fill:#ccf,stroke:#333
B --> C[Transaction]
style C fill:#cff,stroke:#333- Transaction Lifecycle

1journey
2 title Transaction Flow
3 section Initiation
4 User Authentication: 5: User
5 Account Verification: 5: System
6 section Processing
7 Balance Check: 4: System
8 Transaction Execution: 3: System
9 section Completion
10 Update Balance: 5: System
11 Record Transaction: 5: System4.5 Database Operations
Account Creation SQL Equivalent
1INSERT INTO accounts_account (
2 account_type,
3 account_number,
4 balance,
5 created_at,
6 user_id
7) VALUES (
8 'SAVINGS',
9 'ACC-123456789',
10 0.00,
11 NOW(),
12 1
13);Transaction Recording Example
1BEGIN;
2UPDATE accounts_account
3SET balance = balance + 100.00
4WHERE id = 1;
5
6INSERT INTO accounts_transaction (
7 transaction_type,
8 amount,
9 timestamp,
10 account_id
11) VALUES (
12 'DEPOSIT',
13 100.00,
14 NOW(),
15 1
16);
17COMMIT;5. API Endpoints
5.1 Authentication API

5.2 Account API
accounts/api/views.py
1# accounts/api/views.py
2from rest_framework.viewsets import ModelViewSet
3from .serializers import AccountSerializer
4
5class AccountViewSet(ModelViewSet):
6 queryset = Account.objects.all()
7 serializer_class = AccountSerializer
8 permission_classes = [IsAuthenticated]
9
10 def get_queryset(self):
11 return self.request.user.account_set.all()6. Deployment Guide
6.1 Vercel Configuration
vercel.json
1// vercel.json
2{
3 "builds": [
4 {
5 "src": "core/wsgi.py",
6 "use": "@vercel/python",
7 "config": {
8 "maxLambdaSize": "15mb",
9 "runtime": "python3.9"
10 }
11 }
12 ],
13 "routes": [
14 {
15 "src": "/static/(.*)",
16 "dest": "/static/$1"
17 },
18 {
19 "src": "/media/(.*)",
20 "dest": "/media/$1"
21 },
22 {
23 "src": "/(.*)",
24 "dest": "core/wsgi.py"
25 }
26 ]
27}6.2 Deployment Steps
- Local Setup:
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python manage.py migrate- Vercel Deployment:
vercel env add DATABASE_URL
vercel env add SECRET_KEY
vercel env add DEBUG
vercel --prod7. Security Measures
- Data Encryption:
core/settings.py
# core/settings.py
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True- Rate Limiting:
accounts/views.py
# accounts/views.py
from django_ratelimit.decorators import ratelimit
@ratelimit(key='ip', rate='5/m')
def login_view(request):
...- Security Headers:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'csp.middleware.CSPMiddleware',
]
CSP_DEFAULT_SRC = ("'self'", "cdn.vercel.app")8. Testing Strategy
8.1 Authentication Tests
accounts/tests/test_auth.py
1# accounts/tests/test_auth.py
2class AuthenticationTests(TestCase):
3 def test_user_registration(self):
4 response = self.client.post(reverse('signup'), {
5 'email': 'test@example.com',
6 'password1': 'complexpassword123',
7 'password2': 'complexpassword123',
8 'phone_number': '+254712345678',
9 'date_of_birth': '2000-01-01'
10 })
11 self.assertEqual(response.status_code, 302)
12 self.assertEqual(User.objects.count(), 1)9. Troubleshooting
Common Issues:
- Database Connection Errors:
# Test Supabase connection
psql "$DATABASE_URL"
# Check SSL configuration
openssl s_client -connect db.project-ref.supabase.co:6543- Static Files Not Loading:
# Collect static files
python manage.py collectstatic --noinput
# Verify vercel.json routes- Authentication Failures:
# Check email verification status
user = CustomUser.objects.get(email='user@example.com')
print(user.is_verified)Share this article
Send it to someone who would find it useful.
Copied