Django ORM
Django ORMは、DjangoフレームワークのActive Record型ORMです。モデル駆動のデータベース設計、自動マイグレーション、管理インターフェースとの深い統合を特徴とし、PostgreSQL、MySQL、SQLite、Oracle等をサポートします。
GitHub概要
django/django
The Web framework for perfectionists with deadlines.
スター84,248
ウォッチ2,284
フォーク32,718
作成日:2012年4月28日
言語:Python
ライセンス:BSD 3-Clause "New" or "Revised" License
トピックス
appsdjangoframeworkmodelsormpythontemplatesviewsweb
スター履歴
データ取得日時: 2025/7/17 10:32
ライブラリ
Django ORM
概要
Django ORMは、DjangoフレームワークのActive Record型ORMです。モデル駆動のデータベース設計、自動マイグレーション、管理インターフェースとの深い統合を特徴とし、PostgreSQL、MySQL、SQLite、Oracle等をサポートします。
詳細
Django ORMは、Convention over Configurationの思想に基づいて設計されており、最小限の設定でパワフルなデータベース操作を実現します。Pythonクラスとして定義されたモデルから自動的にデータベーステーブルを生成し、直感的なクエリAPIを提供します。Django管理インターフェースとの統合により、CRUD操作を簡単に実行できます。
主な特徴
- Active Recordパターン: モデルクラスに業務ロジックとデータアクセスを統合
- 自動マイグレーション: モデルの変更から自動的にマイグレーションファイルを生成
- 管理インターフェース: モデルの自動CRUD画面生成
- 豊富なフィールドタイプ: 多様なデータ型をサポート
- 強力なクエリセットAPI: 遅延評価による効率的なクエリ実行
メリット・デメリット
メリット
- 学習コストが低く、初心者にも優しい設計
- Django管理インターフェースによる圧倒的な開発生産性
- Python開発者にとって自然で読みやすいAPI
- 豊富なドキュメントとコミュニティサポート
- CRUD中心のWebアプリケーション開発に最適
デメリット
- 複雑なクエリ表現に制限がある場合がある
- Djangoフレームワーク依存のため他のフレームワークでは使用困難
- 大規模システムでのパフォーマンスチューニングが複雑
- ORM抽象化により生SQLの直接制御が困難
参考ページ
書き方の例
インストールと基本セットアップ
pip install Django
django-admin startproject myproject
cd myproject
python manage.py startapp myapp
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp', # アプリケーションを追加
]
基本的なCRUD操作(モデル定義、作成、読み取り、更新、削除)
# models.py
from django.db import models
class User(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Meta:
ordering = ['-created_at']
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField(blank=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
class Meta:
ordering = ['-created_at']
# マイグレーション実行
# python manage.py makemigrations
# python manage.py migrate
# 基本的なCRUD操作
from myapp.models import User, Post
# 作成
user = User.objects.create(
name='田中太郎',
email='[email protected]'
)
# 読み取り
all_users = User.objects.all()
user_by_email = User.objects.get(email='[email protected]')
filtered_users = User.objects.filter(name__icontains='田中')
# 更新
user = User.objects.get(id=1)
user.name = '田中次郎'
user.save()
# 一括更新
User.objects.filter(name__icontains='田中').update(name='更新済み')
# 削除
user = User.objects.get(id=1)
user.delete()
# 一括削除
User.objects.filter(name='テスト').delete()
高度なクエリとリレーションシップ
from django.db.models import Q, Count, Avg, Max, Min
from datetime import datetime, timedelta
# 複雑な条件クエリ
recent_users = User.objects.filter(
Q(created_at__gte=datetime.now() - timedelta(days=30)) &
Q(email__endswith='@company.com')
).order_by('-created_at')[:10]
# JOINクエリ(select_related)
posts_with_author = Post.objects.select_related('author').all()
# 逆参照クエリ(prefetch_related)
users_with_posts = User.objects.prefetch_related('posts').all()
# 集約クエリ
user_stats = User.objects.aggregate(
total_users=Count('id'),
avg_posts=Avg('posts__id'),
latest_user=Max('created_at')
)
# グループ化クエリ
post_counts = User.objects.annotate(
post_count=Count('posts')
).filter(post_count__gt=5)
# サブクエリ
active_users = User.objects.filter(
id__in=Post.objects.values_list('author_id', flat=True).distinct()
)
# 複雑なクエリセット操作
complex_query = Post.objects.select_related('author').filter(
author__email__endswith='@company.com',
created_at__gte=datetime.now() - timedelta(days=7)
).annotate(
author_post_count=Count('author__posts')
).order_by('-created_at', 'title')
# Raw SQLクエリ
users = User.objects.raw(
"SELECT * FROM myapp_user WHERE email LIKE %s",
['%@company.com']
)
マイグレーションとスキーマ管理
# マイグレーションファイル生成
python manage.py makemigrations
# 特定アプリのマイグレーション
python manage.py makemigrations myapp
# マイグレーション実行
python manage.py migrate
# マイグレーション状況確認
python manage.py showmigrations
# マイグレーション SQL確認
python manage.py sqlmigrate myapp 0001
# カスタムマイグレーション
# migrations/0002_custom_migration.py
from django.db import migrations
def forwards_func(apps, schema_editor):
User = apps.get_model('myapp', 'User')
db_alias = schema_editor.connection.alias
User.objects.using(db_alias).filter(
name='old_name'
).update(name='new_name')
def reverse_func(apps, schema_editor):
User = apps.get_model('myapp', 'User')
db_alias = schema_editor.connection.alias
User.objects.using(db_alias).filter(
name='new_name'
).update(name='old_name')
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.RunPython(forwards_func, reverse_func),
]
パフォーマンス最適化と高度な機能
from django.db import transaction
from django.core.cache import cache
# トランザクション管理
@transaction.atomic
def create_user_with_posts():
user = User.objects.create(
name='山田花子',
email='[email protected]'
)
Post.objects.create(
title='最初の投稿',
content='Django ORMを使った投稿です',
author=user
)
return user
# バッチ操作
users_data = [
User(name='ユーザー1', email='[email protected]'),
User(name='ユーザー2', email='[email protected]'),
User(name='ユーザー3', email='[email protected]'),
]
User.objects.bulk_create(users_data)
# バッチ更新
User.objects.bulk_update(
users_data,
['name', 'email']
)
# クエリセット最適化
# N+1問題を回避
efficient_query = Post.objects.select_related('author').prefetch_related(
'author__posts'
).all()
# インデックスヒント
from django.db.models import Index
class User(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
class Meta:
indexes = [
Index(fields=['name', 'email']),
Index(fields=['-created_at']),
]
# カスタムマネージャー
class PublishedPostManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(is_published=True)
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
is_published = models.BooleanField(default=False)
objects = models.Manager() # デフォルトマネージャー
published = PublishedPostManager() # カスタムマネージャー
# 使用例
published_posts = Post.published.all()
フレームワーク統合と実用例
# Django REST Framework統合
from rest_framework import serializers, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
class UserSerializer(serializers.ModelSerializer):
post_count = serializers.SerializerMethodField()
class Meta:
model = User
fields = ['id', 'name', 'email', 'created_at', 'post_count']
def get_post_count(self, obj):
return obj.posts.count()
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
@action(detail=True, methods=['get'])
def posts(self, request, pk=None):
user = self.get_object()
posts = user.posts.all()
return Response([{
'id': post.id,
'title': post.title,
'created_at': post.created_at
} for post in posts])
# Celeryタスク統合
from celery import shared_task
@shared_task
def process_user_data(user_id):
try:
user = User.objects.get(id=user_id)
# 重い処理をバックグラウンドで実行
user.processed = True
user.save()
return f"User {user.name} processed successfully"
except User.DoesNotExist:
return f"User with id {user_id} not found"
# Django管理インターフェース
from django.contrib import admin
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
list_display = ['name', 'email', 'created_at', 'post_count']
list_filter = ['created_at']
search_fields = ['name', 'email']
readonly_fields = ['created_at', 'updated_at']
def post_count(self, obj):
return obj.posts.count()
post_count.short_description = '投稿数'
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ['title', 'author', 'created_at']
list_filter = ['created_at', 'author']
search_fields = ['title', 'content']
autocomplete_fields = ['author']