Xử lý điều kiện trong Django bằng Case và When

Thao tác này tương tự như cấu trúc if-elif-else trong cơ sở dữ liệu.

1. Chuẩn bị dữ liệu

class User(models.Model):
    BASIC = 'B'
    PREMIUM = 'P'
    ELITE = 'E'
    ACCOUNT_TYPE_CHOICES = [
        (BASIC, 'Basic'),
        (PREMIUM, 'Premium'),
        (ELITE, 'Elite'),
    ]
    username = models.CharField(max_length=50)
    registration_date = models.DateField()
    membership_type = models.CharField(
        max_length=1,
        choices=ACCOUNT_TYPE_CHOICES,
        default=BASIC,
    )

Mã tạo dữ liệu mẫu:

from myapp.models import User

User.objects.create(username="user_1", registration_date="2020-01-01", membership_type="B")
User.objects.create(username="user_2", registration_date="2021-07-12", membership_type="P")
User.objects.create(username="user_3", registration_date="2022-09-20", membership_type="E")
User.objects.create(username="user_4", registration_date="2022-12-07", membership_type="E")

2. Thêm trường mới với When và Case

from django.db.models import Case, Value, When

results = User.objects.annotate(
    season_name=Case(
        When(registration_date__month__in=[1, 2, 3], then=Value("Mùa xuân")),
        When(registration_date__month__in=[4, 5, 6], then=Value("Mùa hè")),
        When(registration_date__month__in=[7, 8, 9], then=Value("Mùa thu")),
        When(registration_date__month__in=[10, 11, 12], then=Value("Mùa đông")),
        default=Value("Mùa xuân")
    )
)

Lấy giá trị từ trường khác:

When(registration_date__month__in=[1, 2, 3], then="username")

Sử dụng F() để truy cập trường:

from django.db.models import F
When(registration_date__month__in=[1, 2, 3], then=F("username"))

3. Lọc dữ liệu theo điều kiện

filtered_users = User.objects.annotate(
    season_name=Case(
        When(registration_date__month__in=[1, 2, 3], then=Value("Mùa xuân")),
        When(registration_date__month__in=[4, 5, 6], then=Value("Mùa hè")),
        When(registration_date__month__in=[7, 8, 9], then=Value("Mùa thu")),
        When(registration_date__month__in=[10, 11, 12], then=Value("Mùa đông")),
        default=Value("Mùa xuân")
    )
).filter(season_name="Mùa xuân")

Dùng Case trong filter:

from datetime import date, timedelta

current_date = date.today()
month_ago = current_date - timedelta(days=30)
year_ago = current_date - timedelta(days=365)

User.objects.filter(
    registration_date__lte=Case(
        When(membership_type=User.PREMIUM, then=month_ago),
        When(membership_type=User.ELITE, then=year_ago)
    )
)

4. Cập nhật dữ liệu theo điều kiện

User.objects.update(
    membership_type=Case(
        When(registration_date__year=2020, then=Value(User.ELITE)),
        When(registration_date__year=2021, then=Value(User.BASIC)),
        default=Value(User.PREMIUM)
    )
)

Áp dụng cho năm cụ thể:

User.objects.filter(registration_date__year__in=[2020, 2021]).update(
    membership_type=Case(
        When(registration_date__year=2020, then=Value(User.ELITE)),
        When(registration_date__year=2021, then=Value(User.BASIC)),
        default=Value(User.PREMIUM)
    )
)

Thẻ: django-orm query-annotations conditional-queries database-expressions case-when

Đăng vào ngày 21 tháng 6 lúc 18:02