← Назад к вопросам

Какой тип данных хранится в IntegerChoices?

1.0 Junior🔥 111 комментариев
#Django#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# IntegerChoices: типы данных и использование

IntegerChoices — это класс из Django, который позволяет определять набор именованных целых чисел с удобным интерфейсом выбора. Это комбинирует типизацию с удобством использования.

Основной тип данных

В IntegerChoices хранится целое число (int), а не строка:

from django.db.models import IntegerChoices

class OrderStatus(IntegerChoices):
    PENDING = 1, "Ожидание"
    PROCESSING = 2, "Обработка"
    COMPLETED = 3, "Завершено"
    CANCELLED = 4, "Отменено"

# Проверка типов
print(type(OrderStatus.PENDING))      # <enum 'OrderStatus'>
print(OrderStatus.PENDING.value)      # 1 (целое число)
print(OrderStatus.PENDING.label)      # "Ожидание" (строка)
print(type(OrderStatus.PENDING.value)) # <class 'int'>

Использование в моделях

from django.db import models

class Order(models.Model):
    class Status(IntegerChoices):
        PENDING = 1, "Ожидание"
        PROCESSING = 2, "Обработка"
        COMPLETED = 3, "Завершено"
        CANCELLED = 4, "Отменено"
    
    status = models.IntegerField(
        choices=Status.choices,
        default=Status.PENDING
    )
    # В БД сохраняется целое число: 1, 2, 3 или 4

# Создание записи
order = Order.objects.create(status=Order.Status.PROCESSING)
print(order.status)  # 2
print(order.get_status_display())  # "Обработка" (из label)

TextChoices vs IntegerChoices

# TextChoices — хранит строки
class Color(TextChoices):
    RED = "red", "Красный"
    BLUE = "blue", "Синий"
    GREEN = "green", "Зелёный"

field = models.CharField(choices=Color.choices)
# В БД: 'red', 'blue' или 'green'

# IntegerChoices — хранит целые числа
class Priority(IntegerChoices):
    LOW = 1, "Низкий"
    MEDIUM = 2, "Средний"
    HIGH = 3, "Высокий"

field = models.IntegerField(choices=Priority.choices)
# В БД: 1, 2 или 3

Типизация в коде

from typing import Literal
from django.db.models import IntegerChoices

class PaymentStatus(IntegerChoices):
    PENDING = 1, "В ожидании"
    APPROVED = 2, "Одобрено"
    REJECTED = 3, "Отклонено"

def process_payment(status: Literal[1, 2, 3]) -> str:
    if status == PaymentStatus.APPROVED:
        return "Payment accepted"
    return "Payment declined"

# Или с использованием самого enum
def process_payment(status: PaymentStatus) -> str:
    if status == PaymentStatus.APPROVED:
        return "Payment accepted"
    return "Payment declined"

Практические примеры

Сравнение и фильтрация

class TaskStatus(IntegerChoices):
    NEW = 1, "Новая"
    IN_PROGRESS = 2, "В процессе"
    DONE = 3, "Завершена"
    ARCHIVED = 4, "В архиве"

class Task(models.Model):
    status = models.IntegerField(choices=TaskStatus.choices)

# Фильтрация
active_tasks = Task.objects.filter(
    status__in=[TaskStatus.NEW, TaskStatus.IN_PROGRESS]
)

# Прямое сравнение
if task.status == TaskStatus.DONE:
    task.archived_at = now()

# Получить все значения
all_statuses = list(TaskStatus)
print(all_statuses)  # [1, 2, 3, 4]

# Получить все метки (labels)
status_labels = [label for _, label in TaskStatus.choices]
print(status_labels)  # ["Новая", "В процессе", "Завершена", "В архиве"]

Сериализация для API

from rest_framework import serializers

class TaskSerializer(serializers.ModelSerializer):
    status = serializers.ChoiceField(choices=TaskStatus.choices)
    status_display = serializers.CharField(source='get_status_display', read_only=True)
    
    class Meta:
        model = Task
        fields = ['id', 'title', 'status', 'status_display']

# Response пользователю
{
    "id": 1,
    "title": "Implement feature",
    "status": 2,  # целое число в БД
    "status_display": "В процессе"  # для показа
}

Сериализация в Pydantic

from pydantic import BaseModel
from django.db.models import IntegerChoices

class UserRole(IntegerChoices):
    ADMIN = 1, "Администратор"
    MODERATOR = 2, "Модератор"
    USER = 3, "Пользователь"

class UserResponse(BaseModel):
    id: int
    username: str
    role: int  # IntegerChoices.value это int
    role_label: str  # Метка для отображения

    class Config:
        # Если используем Django модель
        from_attributes = True

Преимущества IntegerChoices

# Сравнение с хардкодом

# ❌ Плохо: магические числа
def is_approved(status):
    return status == 2  # Что такое 2?

# ✅ Хорошо: семантические имена
class DocStatus(IntegerChoices):
    PENDING = 1, "На согласование"
    APPROVED = 2, "Одобрено"
    REJECTED = 3, "Отклонено"

def is_approved(status):
    return status == DocStatus.APPROVED

Итерация и работа с выборами

class Permission(IntegerChoices):
    READ = 1, "Чтение"
    WRITE = 2, "Запись"
    DELETE = 4, "Удаление"
    ADMIN = 8, "Администрирование"

# Итерация
for permission in Permission:
    print(f"{permission.name} = {permission.value} ({permission.label})")
# Output:
# READ = 1 (Чтение)
# WRITE = 2 (Запись)
# DELETE = 4 (Удаление)
# ADMIN = 8 (Администрирование)

# Доступ по имени
print(Permission['READ'])          # Permission.READ
print(Permission['READ'].value)    # 1

# Доступ по значению
print(Permission(2))               # Permission.WRITE
print(Permission(2).label)         # "Запись"

Суммирование: IntegerChoices.choices

class Status(IntegerChoices):
    DRAFT = 1, "Черновик"
    PUBLISHED = 2, "Опубликовано"
    ARCHIVED = 3, "В архиве"

print(Status.choices)
# Вывод: [(1, 'Черновик'), (2, 'Опубликовано'), (3, 'В архиве')]

# Для использования в моделях
class Article(models.Model):
    status = models.IntegerField(choices=Status.choices, default=Status.DRAFT)

Вывод

IntegerChoices хранит целые числа (int), а не строки. Каждый вариант имеет:

  • value — целое число для хранения в БД
  • label — человекочитаемую строку для отображения
  • name — программное имя константы

Это намного удобнее, чем магические числа, и обеспечивает типобезопасность.

Какой тип данных хранится в IntegerChoices? | PrepBro