Data Models
The Django application is split into domain-specific apps. 35 models span
10 apps — the diagrams below show how they relate.
Full entity-relationship diagram
Housing & Safety domain
erDiagram
District {
int id PK
string slug UK
string name
string description
string color
string icon
int order
bool is_active
}
Neighbourhood {
int id PK
string slug UK
string name
int district_id FK
string vibe
string best_for
decimal latitude
decimal longitude
decimal safety_score
string safety_level
decimal violent_crime_score
decimal property_crime_score
decimal gang_safety_score
int avg_rent_1br_min
int avg_rent_1br_max
int avg_property_price
int price_per_sqm
int airbnb_listings
int airbnb_avg_nightly
bool is_active
date metrics_as_of
datetime updated_at
}
NeighbourhoodHighlight {
int id PK
int neighbourhood_id FK
string icon
string label
string value
int order
}
PropertySnapshot {
int id PK
int neighbourhood_id FK
date data_date
int avg_rent_1br
int avg_rent_2br
int avg_property_price
int airbnb_listings
string source
}
Ward {
int id PK
int number UK
string name
json neighborhoods_text
bool is_active
}
WardSafetySnapshot {
int id PK
int ward_id FK
string period_label
date period_start
date period_end
string source_version
decimal overall_score
decimal violent_crime_score
decimal property_crime_score
decimal gang_safety_score
decimal burglary_score
decimal vehicle_crime_score
string trend_direction
bool is_latest
datetime computed_at
}
NeighbourhoodWard {
int id PK
int neighbourhood_id FK
int ward_id FK
decimal weight
date effective_from
date effective_to
}
District ||--o{ Neighbourhood : contains
Neighbourhood ||--o{ NeighbourhoodHighlight : highlights
Neighbourhood ||--o{ PropertySnapshot : tracks
Neighbourhood ||--o{ NeighbourhoodWard : maps_to
Ward ||--o{ NeighbourhoodWard : maps_to
Ward ||--o{ WardSafetySnapshot : has
Content & Commerce domain
erDiagram
Category {
int id PK
string name UK
string slug_category UK
string image_url
bool show_on_home
int order
}
BlogPost {
int id PK
string identifier UK
string title
markdown content
string access
float safety
int category_id FK
int views
float rating
string tags
datetime created_at
datetime updated_at
}
Itinerary {
int id PK
string itineraryID UK
string name
int days
string access
int user_id FK
int views
float rating
string travel_budget
datetime created_at
}
Comment {
int id PK
int blog_post_id FK
int user_id FK
text body
int parent_id FK
bool active
datetime created_at
}
Favorite {
int id PK
string access
int user_id FK
int blog_post_id FK
int itinerary_id FK
datetime created_at
}
TravelMode {
int id PK
string mode UK
}
Category ||--o{ BlogPost : categorises
BlogPost ||--o{ Comment : has
Comment ||--o{ Comment : replies
BlogPost ||--o{ Favorite : saved_as
Itinerary ||--o{ Favorite : saved_as
Itinerary }o--o{ TravelMode : uses
Payments & Subscriptions domain
erDiagram
SubscriptionTier {
int id PK
string tier_id UK
string name
text description
decimal price_eur
string stripe_price_id_test
string stripe_price_id_live
bool includes_data
bool includes_reading
bool includes_ebooks
bool is_active
int sort_order
}
Customer {
int id PK
int user_id FK
string customer_id
string email
}
Subscription {
int id PK
int customer_id FK
int user_id FK
string email
string session_id
string subscription_id
decimal amount
string currency
string status
int tier_id FK
datetime started_at
datetime ended_at
datetime canceled_at
}
GuestSubscription {
int id PK
string email
int tier_id FK
string status
string stripe_subscription_id
string access_token
decimal amount
string currency
datetime activated_at
datetime expires_at
}
Invoice {
int id PK
string invoice_number
string customer_email
decimal amount
string currency
string stripe_session_id
file pdf_file
bool email_sent
bool lexoffice_uploaded
}
StripeCheckoutEvent {
int id PK
string event_id UK
string event_type
bool success
text error_message
datetime processed_at
}
SubscriptionTier ||--o{ Subscription : defines
SubscriptionTier ||--o{ GuestSubscription : defines
Customer ||--o{ Subscription : owns
Reports & Datasets domain
erDiagram
Dataset {
int id PK
string slug UK
string name
string category
string status
string region
string data_bucket
string data_path
string stripe_product_id_test
string stripe_price_id_test
string stripe_product_id_live
string stripe_price_id_live
string current_version
bool workflow_enabled
}
DatasetAccess {
int id PK
int user_id FK
string email
int dataset_id FK
string status
string access_token
string stripe_session_id
decimal amount
datetime paid_at
datetime expires_at
int legacy_purchase_id FK
}
CrimeDataPurchase {
int id PK
int user_id FK
string email
string access_type
string neighborhood_slug
string status
string access_token
decimal amount
datetime paid_at
datetime expires_at
}
Dataset ||--o{ DatasetAccess : grants
CrimeDataPurchase ||--o{ DatasetAccess : migrated_to
Travel Quiz domain
erDiagram
Area {
int id PK
string name
string slug UK
string color
int order
}
QuizNeighbourhood {
int id PK
string name
string slug UK
int area_id FK
string vibe
int walkability
int safety
string wind
int score_ocean
int score_mountain
int score_luxury
int score_budget
int score_nightlife
int score_surf
bool is_active
}
Quiz {
int id PK
string slug UK
string title
text subtitle
bool is_active
int order
}
Question {
int id PK
int quiz_id FK
text text
string question_type
string score_attribute_high
string score_attribute_low
int order
}
QuestionChoice {
int id PK
int question_id FK
string text
int value
string score_attribute
int order
}
QuizResult {
int id PK
int quiz_id FK
int user_id FK
json answers
int top_neighbourhood_id FK
int second_neighbourhood_id FK
int third_neighbourhood_id FK
json scores
datetime created_at
}
Area ||--o{ QuizNeighbourhood : groups
Quiz ||--o{ Question : contains
Question ||--o{ QuestionChoice : has
Quiz ||--o{ QuizResult : produces
QuizNeighbourhood ||--o{ QuizResult : recommended_in
Corrections from prior diagram
The following errors were present in the earlier visual and have been fixed:
See the Auto-generated Reference section for per-model field docs built
from data/models.json.