Shared Concepts¶
This section explains concepts that cut across multiple apps .
These are not owned by a single app, but are consistently reused patterns that define how the system behaves.
If you understand this section, you will:
- stop duplicating logic
- know where to extend vs where to reuse
- avoid breaking invisible contracts between apps
Role-Based Architecture (Customer vs Seller)¶
Core Idea¶
There are no separate user tables for customers and sellers.
Instead:
- One
Usermodel - Role flags define behavior
Why This Matters¶
- A seller can also be a customer
- Same login, same identity
- Shared history (orders, products, support)
Where This Is Used¶
auth_email.LoginView→ role-based redirectsseller.mixins.IsSellerMixincustomer.mixins.IsCustomerMixin- Shared generic views in
users
Customization Guidance¶
Safe:
- Add new roles (e.g.
is_affiliate) - Add role-based panels
Dangerous:
- Splitting User into multiple tables
- Hardcoding role logic inside business apps
Generic Views as a Reuse Contract¶
Concept¶
The users app defines generic, role-agnostic base views .
Examples:
GenericUserProfileViewGenericPasswordChangeViewGenericOrderHistoryViewGenericMyProductListViewGenericMySupportListView
These views:
- contain business-safe logic
- accept presentation config via subclassing
How It Works¶
Each subclass only provides:
base_templateactive_page- optional form class
Why This Is Important¶
- No duplicated logic
- Bug fixes apply everywhere
- Behavior remains consistent
Customization Guidance¶
Safe:
- Add new generic views
- Extend templates
Dangerous:
- Using generic views directly in
urls.py - Changing base logic without checking all consumers
PurchasedProduct as an Access Token¶
Concept¶
PurchasedProduct is not just a table.
It is a permission artifact .
It answers exactly one question:
“Does this user own this product?”
System-Wide Usage¶
Used by:
- Downloads (
payments) - Product listing (
users) - Support eligibility (
depsupport) - Seller analytics (
seller) - Admin visibility (
users/admin.py)
Key Rule¶
If
PurchasedProductdoes not exist, access does not exist.
This rule is never bypassed.
Customization Guidance¶
Safe:
- Add metadata to PurchasedProduct
- Add expiry logic (subscriptions)
Dangerous:
- Granting access without creating PurchasedProduct
- Checking ownership via orders directly
Order Lifecycle vs Access Lifecycle¶
Important Distinction¶
| Concept | Meaning |
|---|---|
| Order | Payment attempt |
| PurchasedProduct | Access grant |
Orders can be:
- pending
- failed
- refunded
PurchasedProduct exists only when:
- payment is successful
- access should be granted
Why This Separation Exists¶
- Refunds revoke access cleanly
- Failed payments do not pollute access
- Admin actions remain reversible
Where This Pattern Appears¶
payments_dodo.webhookpayments.admin- Download views
Signals as Side-Effect Boundaries¶
Concept¶
Signals are used only for side effects , never for business decisions.
Examples:
- Create Dodo customer on user creation
- Sync product with payment provider
- Auto-generate slugs
What Signals Must NOT Do¶
- Decide access
- Change order state
- Trigger irreversible workflows
Why This Rule Exists¶
Signals:
- are implicit
- are hard to debug
- can fire multiple times
They are intentionally limited.
Background Tasks (Celery) as Reliability Layer¶
What Celery Is Used For¶
- Emails
- Telegram notifications
- Database backups
What Celery Is NOT Used For¶
- Granting access
- Payment confirmation
- Core state transitions
Design Principle¶
Business state changes must be synchronous and atomic.
Side effects can be async.
This prevents:
- partial purchases
- ghost access
- race conditions
Middleware as Global Authority¶
Concept¶
Some rules must override all apps .
Example:
- Under construction mode
Why Middleware¶
- Runs before views
- Cannot be bypassed accidentally
- Enforced globally
Rule¶
Only system-level concerns belong in middleware.
Cache as a Performance Optimization, Not Truth¶
Cache Usage¶
- Short URLs
- Under construction state
- Analytics data
Rule¶
Cache may lie. Database must not.
All cached data:
- has TTL
- is safe to invalidate
- has DB fallback
Environment Awareness (Dev vs Prod)¶
Shared Pattern¶
Many components behave differently based on environment:
| Feature | Dev | Prod |
|---|---|---|
| File download | Local FS | Signed S3 URL |
| Storage | Local | DO Spaces |
| DB Backup | Local FS | Cloud |
| Debug | On | Off |
Why This Matters¶
- Local development stays simple
- Production stays secure
- Same codebase, different behavior
Why Shared Concepts Matter More Than Apps¶
Apps can be replaced.
Shared concepts cannot .
If you customize:
- follow the shared rules
- reuse the patterns
- don’t fight the architecture