[Django]モデルを追加した時にmigrateエラーが出ないための方法

django

Djangoで一度、モデルを定義した後に追加することはよくあります。

リレーションモデルを追加したりなどなど。Ruby on Railsではモデルを追加してもmigrateが割とすんなり通ってくれるのですが、Djangoでモデルを追加、編集した時にmigrateエラーでハマってしまったので備忘録を兼ねて解決方法を紹介します。

普通にモデルを追加するとエラーが出る

Webアプリケーションを開発している時に、後からモデルを追加したいことって往々にしてありますよね。

簡単なブログアプリケーションを作ろうと思って、Postモデル(投稿関連)を作った後にCategoryモデルを追加してリレーションを設定しました。

from django.db import models
from django.utils import timezone

# 追加モデル
class Category(models.Model):
    category = models.CharField(max_length=40)

    def __str__(self):
        return self.category

# 元から設定していたモデル
class Post(models.Model):
    author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    category = models.ForeignKey(Category, verbose_name='カテゴリ', on_delete=models.PROTECT,)
    title = models.CharField(max_length=40)
    text = models.TextField()
    created_date = models.DateTimeField(
        default=timezone.now)
    published_date = models.DateTimeField(
        blank=True, null=True)

    def publish(self):
        self.published_date = timezone.now()
        self.save()

    def __str__(self):
        return self.title

追加してmakemigrationsすると、以下のエラーが発生。

You are trying to add a non-nullable field 'xxx' to xxx without a default;
we can't do that (the database needs something to populate existing rows).

Please select a fix:
1) Provide a one-off default now (will be set on all existing rows)
2) Quit, and let me add a default in models.py

で、修正するには①か②を選べと言われます。

①は今、この場でデフォルトを入力しろと言われ入力画面になり何かしらの値を入力することになります。

②は辞めてmodels.pyにデフォルトの値を追加することになります。

要はモデルを追加した時にデフォルトの値が設定されていないことがエラーの原因です。

じゃあ、どうすればいいのか?

これに対応する方法は複数あります。

まず、先に②のパターン。エラーが発生しないように最初からmodels.pyにデフォルト値を記述します。

category = models.CharField(max_length=40, default='SOME CATEGORY')

もしくは、nullの場合でもOKなように以下のように記述します。

category = models.CharField(max_length=40, null=True)

 

最後に①のパターン。基本的には②のように事前にmodels.pyの設定をしていた方がスッキリしますが、間違って①を選択しmigrateエラーにハマってしまった場合。

その場合はエラーが発生していたmigrationsファイルを修正します。

ファイルのoperations以下を修正。

field=models.ForeignKey(to=settings.xxx, default''),

この部分を、以下のように修正。

field=models.ForeignKey(to=settings.xxx, blank=True, null=True),

 

上記、①と②いずれかの対策をすることで、makemigrations→migrateが通るようになります。

 

まとめ

Ruby on Railsではモデルの追加時にこういったエラーにハマることはなかったなぁと回顧。

他のマイグレーションエラーには遭遇しましたが。

モデルを後から追加することは往々にしてあるので、参考にしてみてください。



カテゴリー