Django-モデルのプライマリキーをUUIDにする
|
Djangoでは、モデルのプライマリーキーがシーケンスによって決まります。
つまり下記のように、データベースに挿入されたレコードのidが連番になります。
id: 1 field: hogehgoe
id: 2 field: mogumogu …
このidをUUIDに変更します。
UUIDは次のような利点があります。
- 衝突の回避-UUIDの一意性はグローバルなので、異なるモデルが同じidを持つ可能性が発生しない
- データベーステーブルのサイズの予測を回避
- idの推測を回避
2について。単純に整数がインクリメントされる方式だと、データのサイズを外部から容易に推測できてしまいます。例えばidが3なら3番目のレコード、という具合にです。UUIDにすればデータベースのサイズを予測できなくなります。
3について。例えばhttps://hogehoge.com/user/profile/1という感じで、idを用いてURLを生成することがあります。このように整数だと予測が簡単なので、攻撃を受けやすくなります。しかしUUIDは予測困難なので、不正にデータへアクセスしようとする自体を防ぐことができます。
そのため、特に理由がない場合はUUIDを使うほうが良く、HerokuのPostgreSQL担当者もUUIDの使用を推奨しています。
*参考 http://postgres-bits.herokuapp.com/#58
idをuuidに変更する方法
models.pyで定義したモデルクラスで、UUIDFiledを使ってidの型を指定します。
import uuid
from django.db import models
class MyUUIDModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# other fields
例えばAbstractBaseUserからUserモデルを拡張したケースだと、次のようになります。
import uuid
.....
class User(AbstractBaseUser, PermissionsMixin):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
.....
まとめ
とても簡単に実装できましたが、すでに稼働中のプロジェクトでUUIDに切り替えるのは難しいので、よほどの理由がない限りは避けたほうが良さそうです。開発段階や新規のプロジェクトで使っていこうと思います。