Course Introduction & Project Setup
Welcome to Django CRM!
Why Django for CRM?
Project Scope & Features
Python & Virtual Env Setup
Installing Django
Your First Django Project
Creating Your First App
Configuring settings.py
Database Setup
Static Files Configuration
Templates Configuration
URL Routing Basics
Creating a Home Page
Project Structure Review
Designing Robust CRM/Intranet Data Models
Why Models Matter
Your First CRM Model
Essential Field Types
Model Meta Options
Model Managers & QuerySets
One-to-Many with ForeignKey
Many-to-Many with M2MField
One-to-One with OneToOneField
Self-Referential Relationships
Intermediate Models (Through)
Abstract Base Classes
Model Inheritance Strategies
Custom Model Managers
Model Validation & Clean
Designing for Scalability
Understanding Class-Based Views (CBVs) Fundamentals
Why CBVs?
CBV Basics: The 'View' Class
CBV Flow: Request to Response
Mixins: Your CBV Superpowers
Generic CBVs: The Building Blocks
Displaying Data: `TemplateView`
Listing Records: `ListView`
Detailing Records: `DetailView`
Handling Forms: `FormView`
Creating Records: `CreateView`
Updating Records: `UpdateView`
Deleting Records: `DeleteView`
Customizing CBV Templates
URL Patterns for CBVs
When to Go Custom (or Not)
Implementing Basic List Views with `ListView`
Why ListView?
Your First ListView
The Default Template
Custom Template Name
Custom Context Variable
QuerySet Power-Up
Dynamic QuerySets
Adding Context Data
Empty List Handling
Displaying Contacts
Listing Companies
Tasks Overview
ListView Template Structure
ListView & URL Namespaces
What's Next: DetailView
Detailing Individual Records with `DetailView`
What's a DetailView?
Your First DetailView
DetailView URL Patterns
Customizing the Queryset
Context Data for DetailView
Template Naming & Location
Using Slugs in URLs
Slug Field Customization
Multiple Lookup Fields
Handling 404s Gracefully
Related Objects in Detail
DetailView & Permissions
CRM Contact Detail
Intranet Task Detail
Company Profile View
Handling Forms with `FormView`
Why FormView?
Your First FormView
FormView's Template Context
Processing POST Requests
Success Redirection
Customizing `form_valid`
Built-in Field Validation
Custom Field Validation
Form-Wide Validation
Initial Form Data
Customizing `get_context_data`
Handling Multiple Forms
Contact Us Form
Newsletter Signup
Feedback Form
Creating New Records with `CreateView`
Why CreateView?
CreateView's Core Mechanics
Your First CreateView
Choosing Form Fields
Customizing Form Classes
Where to Next? success_url
Dynamic Redirection
Initial Form Data
Context for Templates
Form Validations
Saving with a Twist
Who Created This?
Permission to Create
Testing Your CreateView
CreateView Best Practices
Updating Existing Records with `UpdateView`
Why UpdateView?
Your First UpdateView
Pre-populating the Form
Success! Where to Next?
Template Context for Updates
Customizing the Form
Which Fields to Update?
Overriding form_valid()
Handling Invalid Forms
Dynamic Initial Data
URL Parameters for Updates
Who Can Update This?
UpdateView & Related Objects
UpdateView Best Practices
UpdateView vs. Custom View
Deleting Records with `DeleteView`
Why DeleteView?
DeleteView's Core Mechanics
Basic DeleteView Setup
The Confirmation Page
Success Redirection
Context for Confirmation
Protecting DeleteView
CSRF Protection
User Feedback
Custom Delete Logic
Soft Deletion
Handling Related Objects
DeleteView in Action
Error Handling & UX
Review & Best Practices
Introduction to `django-tables2`
Why django-tables2?
Installation & Setup
Your First Table Class
Table in a View
Rendering Your Table
Column Ordering
Renaming Columns
Hiding Columns
Empty Table Message
Table Attributes
Column Definitions
Accessing Row Data
Table Data Sources
Table Context
Debugging Tables
Customizing `django-tables2` Columns
Column Types Overview
Adding a Link Column
Customizing Link Text
Template Column Basics
Template Column Context
Custom Column Methods
Formatting with Filters
Custom Formatting Logic
Boolean Column Display
Orderable Columns
Hiding Columns
Column Attributes
Actions Column
Dynamic Column Generation
Refining Table Display
Styling `django-tables2` Tables
Default Table Styling
Adding CSS Classes
Styling Table Headers
Styling Table Rows
Styling Table Cells
Bootstrap Setup
Bootstrap Table Class
Bootstrap Table Variants
Responsive Tables
Contextual Table Rows
Custom Column Templates
Custom Table Templates
Styling Pagination
Styling Empty Tables
CSS Best Practices
Adding Pagination to `django-tables2`
Why Paginate Tables?
Pagination Basics in Django
How `django-tables2` Paginates
Enabling Pagination
Displaying Pagination Controls
Customizing Items Per Page
Handling Empty Tables
Customizing Pagination Template
Pagination with `RequestConfig`
Pagination in `ListView`
Custom Pagination Logic
Pagination with Filtering
Common Pagination Issues
Performance Considerations
Pagination Best Practices
Enabling Sorting in `django-tables2`
Sorting: The Basics
Default Sort Behavior
Making Columns Sortable
Disabling Column Sorting
Initial Sort Order
Sorting Related Fields
Custom Sort Logic
Sorting Template Columns
Sorting Link Columns
Multiple Column Sorting
How Sorting Works
Sorting & QuerySets
Sorting Indicators
Sorting & Pagination
Troubleshooting Sorting
Basic Filtering with `django-tables2`
Why Filter Tables?
Meet `django-filter`
Installation & Setup
Your First FilterSet
Text Search Filters
Dropdown Filters
FilterSet in Your ListView
Rendering the Filter Form
Table + Filter = Magic
Number & Date Filters
Boolean & Null Filters
Multiple Choice Filters
Clear Filters Button
Showing Active Filters
Best Practices for Filtering
Introduction to `DataTables.js`
Why DataTables.js?
DataTables.js Features
Setup: CDN & Local
Your First Data Table
Basic Options & Config
Data from HTML
Data from JavaScript Array
Data from JSON Objects
AJAX Data Source (Client)
AJAX Data Source (Server)
Styling with Bootstrap
Customizing Columns
Internationalization
Events & Callbacks
Responsive Design
Integrating `DataTables.js` with Static HTML
The Static HTML Table
Linking DataTables.js
Your First Data Table
Enabling Basic Features
Customizing Table Display
Column Definitions
Django View for Tables
Dynamic Table Data
Styling Your Table
`DataTables.js` with AJAX Data Source (Client-Side)
Why AJAX for DataTables?
Django's JSON Response
DataTables.js AJAX Option
Mapping Data to Columns
Initial Data Fetch
Customizing AJAX Requests
Processing AJAX Data
Rendering Complex Columns
Error Handling for AJAX
Refreshing Table Data
Model Data to JSON
Dynamic Column Generation
URL Routing for AJAX
Context for DataTables.js
Putting It All Together
`DataTables.js` Server-Side Processing Setup
Why Server-Side?
Client vs. Server Flow
The Server-Side Option
Setting the AJAX URL
Request Method & Data
Column Definitions for Server
The 'draw' Parameter
Pagination Parameters
Global Search Parameters
Column Search Parameters
Sorting Parameters
Required Response Format
Sending 'recordsTotal'
Sending 'recordsFiltered'
Sending 'data' Array
Implementing `DataTables.js` Server-Side Processing in Django
Why Server-Side?
The Server-Side Dance
Django's JSON Response
The 'Draw' Parameter
Pagination: Start & Length
Global Search: The 'Search' Param
Column-Specific Search
Sorting: The 'Order' Param
The Server-Side View
Dynamic Column Mapping
Handling Related Data
Customizing Data Output
Error Handling & Security
Refactoring with Mixins
Putting It All Together
Advanced `DataTables.js` Features (Search & Column Visibility)
Global Search Refresher
Custom Global Search Input
Column-Specific Search
Dropdown Column Filters
Server-Side Search Logic
Intro to Column Visibility
Basic Toggle Buttons
Column Visibility Menu
Integrating with Buttons Ext.
Responsive Design & Visibility
Search Delay & Debounce
Pre-filling Search Filters
Saving User Preferences
Complex Search Scenarios
Accessibility & UX
Introduction to `django-filter`
Why Filter Data?
Meet django-filter
Installation & Setup
The FilterSet Class
Basic Model Filtering
Applying Filters in Views
Text & Number Filters
Boolean & Date Filters
Relationship Filters
Customizing Filter Fields
Excluding Fields
Ordering Filters
Rendering Filter Forms
Initial Filter Values
What's Next?
Integrating `django-filter` with `ListView`
The Filtered ListView
Connecting FilterSet to ListView
Rendering the Filter Form
Text Search Filters
Exact Match Filters
Boolean & Null Filters
Filtering by Foreign Key
Filtering by Many-to-Many
Filtering by Date & Range
Initial Filter Values
Clearing Filters
Combining Filters & Pagination
Combining Filters & Sorting
Styling Filter Forms
Filter Form Layouts
Customizing `django-filter` Forms and Widgets
Basic Form Styling
Using Django Widgets
Customizing Widget Attributes
Date Range Filters
Number Range Filters
Multiple Choice Filters
Boolean Filters
Manual Form Rendering
Bootstrap Integration
Custom Filter Widgets
Custom Filter Methods
Initial Filter Values
Dynamic Filter Choices
Filter Grouping & Layouts
Resetting Filters
Implementing Custom Search Logic in CBVs
Why Custom Search?
Search in a CBV Context
Basic Text Search
Multiple Field Search
Case-Insensitive Search
Intro to Q Objects
Combining Q Objects (OR)
Combining Q Objects (AND)
Negating Q Objects (NOT)
Complex Q Object Nesting
Dynamic Q Object Building
Search Across Related Models
Date Range Search
Numeric Range Search
Integrating Search with Pagination
Optimizing Queries with `select_related`
Why Optimize Queries?
Django ORM Basics Refresher
Introducing `select_related`
Basic `select_related` Usage
Chaining `select_related`
When to Use `select_related`
Debugging Query Performance
Filtering with Related Fields
Performance Impact Analysis
Optimizing Queries with `prefetch_related`
Why `prefetch_related`?
What is `prefetch_related`?
Basic `prefetch_related` Use
Reverse FKs with `prefetch`
Prefetching Generic Relations
Prefetching Multiple Relations
Nested Prefetching
Custom Prefetch QuerySets
Prefetching with `to_attr`
Prefetching with `queryset`
select_related vs. prefetch
Combining Optimizations
Performance Impact
Common Pitfalls
When Not to Prefetch
Advanced ORM Optimization (`only`, `defer`)
Why Optimize Fields?
Introducing `only()`
Using `only()` in Practice
Introducing `defer()`
Using `defer()` in Practice
Chaining `only()` and `defer()`
Related Fields with `only()`
Related Fields with `defer()`
When to Use Which?
Impact on Memory & Speed
Optimizing `django-tables2`
Optimizing `DataTables.js`
When Not to Optimize Fields
Debugging Field Loading
Best Practices & Summary
User Authentication and Session Management
Auth System Overview
User Model Deep Dive
Custom User Model
Login View Setup
Logout View Setup
Login/Logout URLs
Session Basics
Session Security
Password Reset
Authorization and Permissions (Django's Built-in)
Permission Basics
Creating Custom Permissions
Assigning Permissions
Function View Permissions
CBV Permissions: Mixin
CBV Permissions: `get_permission_required`
Login Required Views
User Passes Test Mixin
Combining Mixins
Permissions in Templates
Checking Permissions in Code
Filtering Querysets by Perms
CRM View Permissions
Intranet Task Permissions
Permission Best Practices
Implementing Object-Level Permissions
Why Object Permissions?
Approaches to OLP
Custom OLP: The Basics
Custom OLP: Mixins
Custom OLP: Queryset Filtering
Meet django-guardian
Assigning Permissions
Checking Permissions
Guardian Mixins for CBVs
Guardian for List Views
Custom Guardian Backends
Permissions for Related Objects
Admin Integration with Guardian
Testing Object Permissions
OLP Best Practices
Best Practices for Intranet/CRM Development
CSRF: The Silent Threat
XSS: Injecting Malice
SQL Injection: Data Defense
Secure Data Handling
Session & Cookie Security
Project Layout & Apps
Settings Management
Unit Testing Your Views
Testing Forms & Models
Integration & End-to-End Tests
Choosing a Deployment Strategy
Preparing for Production
Serving Static & Media Files
Monitoring & Logging
Maintenance & Updates