Models, Migrations & Database

Models, migrations, DB setup, querying, relationships. Superuser, register models, customize admin. Deep dive into databases, ORM, SQL vs NoSQL.

1

Database Fundamentals

Before diving into Django models and migrations, it's essential to understand what databases are, why we need them, and how they work.

What is a Database?

  • A structured collection of data organized for efficient storage and retrieval
  • Acts as a digital filing cabinet for your application's information
  • Provides a way to store, organize, and manage large amounts of data
  • Ensures data integrity, consistency, and security

Databases are the backbone of most web applications. They store everything from user accounts and blog posts to e-commerce products and financial transactions.

Why Do We Need Databases?

  • Persistent Storage: Data survives application restarts and server crashes
  • Data Organization: Structured way to store and organize information
  • Data Relationships: Connect related data (users and their posts)
  • Data Integrity: Ensure data accuracy and consistency
  • Concurrent Access: Multiple users can access data simultaneously
  • Performance: Fast data retrieval and efficient storage

Without databases, we'd have to store data in files, which would be inefficient, insecure, and difficult to manage for complex applications.

2

SQL vs NoSQL Databases

There are two main categories of databases: SQL (relational) and NoSQL (non-relational). Understanding the differences helps you choose the right database for your project.

SQL (Relational) Databases

  • Structured data organized in tables with rows and columns
  • Uses SQL (Structured Query Language) for data manipulation
  • Enforces data relationships and constraints
  • Examples: PostgreSQL, MySQL, SQLite, Oracle
  • ACID compliance (Atomicity, Consistency, Isolation, Durability)
  • Best for: Complex queries, data relationships, financial data

NoSQL (Non-Relational) Databases

  • Flexible data structures (documents, key-value pairs, graphs)
  • No fixed schema - data structure can evolve
  • Horizontal scaling and high performance
  • Examples: MongoDB, Redis, Cassandra, Neo4j
  • Eventually consistent (BASE model)
  • Best for: Big data, real-time applications, flexible schemas

SQL databases are like spreadsheets with relationships, while NoSQL databases are like flexible document storage systems. Each has its strengths and use cases.

When to Use SQL vs NoSQL

  • Use SQL when: You need complex queries, data relationships, ACID compliance
  • Use NoSQL when: You need flexibility, scalability, real-time processing
  • SQL is better for: E-commerce, banking, content management systems
  • NoSQL is better for: Social media, IoT, real-time analytics
3

What is ORM & Why Use It?

ORM stands for Object-Relational Mapping. It's a programming technique that lets you interact with databases using object-oriented programming concepts instead of writing raw SQL.

What is ORM?

  • A bridge between object-oriented code and relational databases
  • Converts database tables to Python classes (models)
  • Converts database rows to Python objects
  • Handles SQL generation automatically
  • Provides a high-level interface for database operations

Think of ORM as a translator between your Python code and the database. Instead of writing SQL queries, you work with Python objects and methods.

Benefits of ORM

  • Productivity: Write less code, focus on business logic
  • Database Agnostic: Switch databases without changing code
  • Security: Automatic SQL injection protection
  • Maintainability: Cleaner, more readable code
  • Type Safety: Better error detection and IDE support
  • Migration Support: Easy database schema changes

ORM vs Raw SQL

  • ORM: Higher level, more abstract, database-agnostic
  • Raw SQL: Lower level, more control, database-specific
  • ORM: Faster development, automatic optimizations
  • Raw SQL: Better performance for complex queries
  • ORM: Easier to maintain and modify
  • Raw SQL: More precise control over queries

Django's ORM is one of the most powerful and user-friendly ORMs available. It provides a rich set of features while maintaining excellent performance.

4

Django Models & Model Fields

Django models are Python classes that represent database tables. They define the structure of your data and the relationships between different pieces of information.

What are Django Models?

  • Python classes that inherit from django.db.models.Model
  • Each model represents a database table
  • Model fields represent table columns
  • Model methods represent business logic
  • Models handle data validation and constraints

Models are the 'M' in Django's MVT architecture. They define your data structure and provide an interface for interacting with the database.

Common Model Field Types

  • CharField: Short text (e.g., names, titles)
  • TextField: Long text (e.g., blog content, descriptions)
  • IntegerField: Whole numbers (e.g., age, count)
  • DecimalField: Decimal numbers (e.g., prices, ratings)
  • DateTimeField: Date and time (e.g., created_date, updated_date)
  • BooleanField: True/False values (e.g., is_active, is_published)
  • EmailField: Email addresses with validation
  • URLField: URLs with validation
  • FileField: File uploads
  • ImageField: Image uploads with validation

Each field type has specific parameters like max_length, null, blank, default, and choices that control how the data is stored and validated.

Model Field Parameters

  • max_length: Maximum length for text fields
  • null: Allow NULL values in database
  • blank: Allow empty values in forms
  • default: Default value for the field
  • unique: Ensure field values are unique
  • choices: Predefined choices for the field
  • help_text: Help text for forms
  • verbose_name: Human-readable name
5

Model Relationships & Foreign Keys

Real-world data is interconnected. Users have posts, posts have comments, products belong to categories. Django models support various types of relationships to represent these connections.

Types of Model Relationships

  • One-to-One: Each record in one table relates to exactly one record in another
  • One-to-Many: Each record in one table can relate to multiple records in another
  • Many-to-Many: Records in both tables can relate to multiple records in the other
  • Self-Referential: A model relates to itself (e.g., employee hierarchy)

Relationships are defined using special field types that Django provides. These fields automatically handle the database constraints and provide convenient methods for accessing related data.

Relationship Field Types

  • ForeignKey: One-to-many relationships (e.g., user and posts)
  • OneToOneField: One-to-one relationships (e.g., user and profile)
  • ManyToManyField: Many-to-many relationships (e.g., posts and tags)
  • GenericForeignKey: Relationships to any model type

Foreign keys are the most common relationship type. They create a link between two tables where one table references another table's primary key.

Relationship Examples

  • User → Posts: One user can have many posts
  • Post → Comments: One post can have many comments
  • Category → Products: One category can have many products
  • Student → Courses: Many students can take many courses
  • Employee → Manager: Self-referential relationship

Django automatically creates reverse relationships, so you can access related data from both sides of the relationship.

6

Database Migrations

Migrations are Django's way of propagating changes you make to your models into your database schema. They're like version control for your database structure.

What are Migrations?

  • Python files that describe database schema changes
  • Track the evolution of your database structure
  • Allow you to version control your database schema
  • Enable team collaboration on database changes
  • Provide rollback capabilities for schema changes

When you change your models (add fields, change field types, etc.), Django creates migration files that describe these changes. These migrations can then be applied to update the database schema.

Migration Process

  • 1. Make changes to your models (add/remove/change fields)
  • 2. Create migration files using 'python manage.py makemigrations'
  • 3. Review the generated migration files
  • 4. Apply migrations using 'python manage.py migrate'
  • 5. Django updates the database schema accordingly

Migration Commands

  • makemigrations: Create migration files from model changes
  • migrate: Apply migrations to the database
  • showmigrations: List all migrations and their status
  • sqlmigrate: Show SQL for a specific migration
  • migrate --fake: Mark migrations as applied without running them

Migrations are essential for maintaining database consistency across different environments (development, staging, production) and for team collaboration.

7

Database Querying & ORM Queries

Django's ORM provides a powerful and intuitive way to query your database. Instead of writing raw SQL, you use Python methods and objects to retrieve and manipulate data.

Basic Query Operations

  • all(): Retrieve all records from a table
  • get(): Retrieve a single record by ID or unique field
  • filter(): Retrieve records that match certain criteria
  • exclude(): Retrieve records that don't match criteria
  • order_by(): Sort records by specific fields
  • limit/offset: Control the number of records returned

Django's ORM uses a query builder pattern, which means you can chain multiple methods together to build complex queries.

Query Methods & Examples

  • User.objects.all() - Get all users
  • Post.objects.filter(author=user) - Get posts by specific user
  • Product.objects.filter(price__gte=100) - Get products >= $100
  • Comment.objects.order_by('-created_date') - Get comments, newest first
  • Post.objects.filter(title__icontains='django') - Search for posts containing 'django'

Advanced Query Features

  • Field lookups: exact, contains, startswith, endswith
  • Number lookups: gt, gte, lt, lte, range
  • Date lookups: year, month, day, hour, minute
  • Aggregation: count, sum, avg, min, max
  • Annotations: Add computed fields to queries
  • Select_related: Optimize foreign key queries
  • Prefetch_related: Optimize many-to-many queries

Django's ORM automatically generates optimized SQL queries and provides protection against common issues like SQL injection attacks.

8

Django Admin Interface

Django's admin interface is one of its most powerful features. It automatically generates a web-based interface for managing your application's data.

What is Django Admin?

  • Automatic web interface for database management
  • Built-in authentication and authorization
  • CRUD operations (Create, Read, Update, Delete)
  • Customizable and extensible
  • No need to build custom admin panels

The admin interface is like having a built-in content management system for your application. It's perfect for managing data, especially during development and for non-technical users.

Admin Features

  • User authentication and permissions
  • Automatic form generation from models
  • Search and filtering capabilities
  • Bulk operations on multiple records
  • Custom actions and workflows
  • Responsive design for mobile devices
  • Integration with Django's security features

Setting Up Admin

  • Create a superuser account
  • Register models in admin.py
  • Customize admin interface
  • Configure permissions and access
  • Add custom actions and methods

The admin interface is highly customizable. You can control which fields are displayed, add custom actions, modify the interface layout, and integrate with your application's business logic.

9

Creating Superuser & Admin Customization

A superuser is a special user account that has full access to the Django admin interface and can perform all administrative tasks.

What is a Superuser?

  • Administrative user with full permissions
  • Can access and modify all data in the admin
  • Can create, edit, and delete any records
  • Can manage other users and their permissions
  • Essential for application administration

Superusers are typically created during the initial setup of your application and are used for administrative tasks like managing content, users, and system configuration.

Admin Customization Options

  • ModelAdmin class: Customize how models appear in admin
  • list_display: Control which fields are shown in list view
  • list_filter: Add filters for easy data filtering
  • search_fields: Enable search functionality
  • ordering: Set default ordering for records
  • readonly_fields: Make fields read-only
  • fieldsets: Organize fields into groups
  • inlines: Show related models inline

Admin customization allows you to create a user-friendly interface that matches your application's specific needs and workflows.

Admin Best Practices

  • Only give superuser access to trusted individuals
  • Use custom permissions for different user roles
  • Customize admin interface for better usability
  • Add helpful actions and methods
  • Implement proper security measures
  • Regularly backup admin data
10

Database Optimization & Best Practices

As your application grows, database performance becomes crucial. Understanding optimization techniques helps ensure your application remains fast and responsive.

Database Optimization Techniques

  • Indexing: Add indexes to frequently queried fields
  • Query optimization: Use select_related and prefetch_related
  • Database normalization: Organize data efficiently
  • Caching: Store frequently accessed data in memory
  • Connection pooling: Reuse database connections
  • Query analysis: Monitor and analyze slow queries

Database optimization is an ongoing process. You should regularly monitor your application's performance and make adjustments as needed.

Common Performance Issues

  • N+1 queries: Multiple queries for related data
  • Missing indexes: Slow queries on unindexed fields
  • Large result sets: Loading too much data at once
  • Inefficient queries: Complex queries that could be simplified
  • Connection overhead: Creating too many database connections

Best Practices

  • Use appropriate field types and constraints
  • Implement proper indexing strategies
  • Monitor query performance regularly
  • Use database transactions when appropriate
  • Implement proper backup and recovery procedures
  • Consider database scaling strategies

Remember that premature optimization can lead to complex, hard-to-maintain code. Focus on writing clean, readable code first, then optimize based on actual performance bottlenecks.