Chuyển đến nội dung chính

Bài 2: Models & Django ORM

Django ORM, model fields, relationships (ForeignKey, OneToOne, ManyToMany). Meta options, managers, custom querysets. Migrations CLI, database routers.

💻 Lập trình — Bài 2 Bài 2: Models & Django ORM

Django: Từ Cơ bản đến Nâng cao

Phần 1: Django Fundamentals

xdev.asia

1. Model Fields

from django.db import models
import uuid

class Product(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=255)
    slug = models.SlugField(unique=True)
    description = models.TextField(blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    stock = models.PositiveIntegerField(default=0)
    is_active = models.BooleanField(default=True)
    image = models.ImageField(upload_to='products/', blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['slug']),
            models.Index(fields=['is_active', '-created_at']),
        ]

    def __str__(self):
        return self.name

2. Relationships

class Category(models.Model):
    name = models.CharField(max_length=100)
    parent = models.ForeignKey(
        'self', on_delete=models.CASCADE,
        null=True, blank=True, related_name='children'
    )

class Product(models.Model):
    category = models.ForeignKey(
        Category, on_delete=models.PROTECT, related_name='products'
    )
    tags = models.ManyToManyField('Tag', blank=True, related_name='products')

class ProductDetail(models.Model):
    product = models.OneToOneField(
        Product, on_delete=models.CASCADE, related_name='detail'
    )
    weight = models.FloatField()
    dimensions = models.JSONField(default=dict)

3. QuerySet API

# CRUD
product = Product.objects.create(name='Laptop', price=999)
product.name = 'Gaming Laptop'
product.save()

# Query
products = Product.objects.filter(
    is_active=True,
    price__lte=1000,
    category__name='Electronics'
).exclude(stock=0).order_by('-price')[:10]

# Aggregation
from django.db.models import Avg, Count, Sum, Q, F

stats = Product.objects.aggregate(
    avg_price=Avg('price'),
    total_stock=Sum('stock'),
    active_count=Count('id', filter=Q(is_active=True)),
)

# F expressions — database-level operations
Product.objects.filter(id=product_id).update(stock=F('stock') - 1)

# Q objects — complex queries
products = Product.objects.filter(
    Q(name__icontains='laptop') | Q(description__icontains='laptop'),
    Q(price__gte=500) & Q(price__lte=2000),
)

4. Custom Managers

class ActiveManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(is_active=True)

class ProductQuerySet(models.QuerySet):
    def active(self):
        return self.filter(is_active=True)

    def in_stock(self):
        return self.filter(stock__gt=0)

    def expensive(self, min_price=100):
        return self.filter(price__gte=min_price)

class Product(models.Model):
    # ...
    objects = models.Manager()  # Default
    active_objects = ActiveManager()
    custom = ProductQuerySet.as_manager()

# Usage
Product.custom.active().in_stock().expensive(500)

5. Migrations

python manage.py makemigrations        # Tạo migration files
python manage.py migrate                # Apply migrations
python manage.py showmigrations         # Xem trạng thái
python manage.py sqlmigrate users 0001  # Xem SQL
python manage.py migrate users 0001     # Rollback về migration cụ thể

Bài tiếp theo: Views, URLs & Templates — FBV, URL routing, template language.