デフォルトなしでnull不可のフィールド 'new_field'をuserprofileに追加しようとしています


108

Django 1.7以降では、Southやその他の移行システムを使用する必要がないため、単純なコマンドを使用しているだけです。 python manage.py makemigrations

しかし、私が得るすべてはこのエラーです:

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

これがmodels.pyです:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    website = models.URLField(blank=True)
    new_field = models.CharField(max_length=140)

オプションとは何ですか?


3
この問題は、新しいテーブルを作成するときではなく、既存のテーブルを変更するときに発生することを付け加えておきます。
x-yuri 2017年

回答:


91

デフォルト値を指定する必要があります。

new_field = models.CharField(max_length=140, default='SOME STRING')

new_fieldにWebサイトのフィールドのコピーが必要な場合はどうすればよいですか。それはどのように見えるべきですか?default = website仕事をしません
IrmantasŽelionis2014年

7
最初に偽のデフォルト値で移行を行い、次にデータ移行を作成して各レコードを反復処理し、に設定new_fieldwebsiteます。
dgel、2014年

CharFieldのデフォルトはオプションである必要があります
フローレント

87

場合あなたが開発サイクルの初期段階にあり、気にしないあなたの現在についてのデータベースのデータあなたはそれを削除してから移行することができます。しかし、最初にマイグレーションdirをクリーンアップし、その行をテーブルから削除する必要があります(django_migrations)

rm  your_app/migrations/*

rm db.sqlite3
python manage.py makemigrations
python manage.py migrate

8
もう一つ。移行テーブルをクリーンアップする必要があります。例:mysql -u[user] [database] -e "delete from django_migrations where app=[your_app]"
Helpe

これが道です。Djangoは移行やモデル検出などが苦手だと思います。このためのメジャーアップデートが必要です。
WesternGun 2018年

移行からすべてのファイルを削除し、django_migrationsからすべての行を削除しました。実行すると、「django.db.migrations.exceptions.NodeNotFoundError:Migration stories.0001_initial dependency reference nonexistent parent node( 'sources'、 '0002_auto_20180903_1224')」が発生します移行。
brainLoop 2018

1
また、必ず削除していないことが__init__.py makemigrationsが作業しませんそれ以外の場合は、あなたが後でそれを復元、移行から、またはstackoverflow.com/a/46362750/1649917
NMU

python manage.py sqlmigrate name_of_your_app nb_of_the_migrationまた、必須
zar3bski

37

1つのオプションは、 'new_field'のデフォルト値を宣言することです。

new_field = models.CharField(max_length=140, default='DEFAULT VALUE')

別のオプションは、「new_field」をnull許容フィールドとして宣言することです。

new_field = models.CharField(max_length=140, null=True)

「new_field」をヌル可能フィールドとして受け入れる場合は、「no input」を「new_field」の有効な入力として受け入れることができます。次に、blank=Trueステートメントも追加する必要があります。

new_field = models.CharField(max_length=140, blank=True, null=True)

でもとともにnull=True、および/またはblank=True必要な場合は、デフォルト値を追加することができます。

new_field = models.CharField(max_length=140, default='DEFAULT VALUE', blank=True, null=True)

7
«CharFieldやTextFieldなどの文字列ベースのフィールドではnullを使用しないでください。文字列ベースのフィールドにnull = Trueがある場合、それは「データなし」の2つの可能な値があることを意味します:NULLと空の文字列。» — モデルフィールドリファレンス
Chema

7

開発サイクルの初期にいる場合は、これを試すことができます-

そのモデルとそのすべての使用法を削除/コメントします。移行を適用します。これにより、そのモデルが削除されてから再びモデルが追加され、移行が実行され、新しいフィールドが追加されたクリーンなモデルが作成されます。


そして、クリーンアップの移行テーブルdjango_migrationsここで概説として:stackoverflow.com/questions/26185687/...ちょうどまたはGUIを使用して、必要な行を削除します。
RusI

4

「website」を空にすることができる場合は、空new_fieldに設定する必要があります。

ここでnew_field、「website」から値を取得するためにif が空の場合に保存のロジックを追加する場合は、次のModelように保存関数をオーバーライドするだけです。

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    website = models.URLField(blank=True, default='DEFAULT VALUE')
    new_field = models.CharField(max_length=140, blank=True, default='DEFAULT VALUE')

    def save(self, *args, **kwargs):
        if not self.new_field:
            # Setting the value of new_field with website's value
            self.new_field = self.website

        # Saving the object with the default save() function
        super(UserProfile, self).save(*args, **kwargs)

4

誰かがを設定している場合はForeignKey、デフォルトを設定せずにnull許容フィールドを許可できます。

new_field = models.ForeignKey(model, null=True)

データベース内にすでにデータが保存されている場合は、デフォルト値を設定することもできます。

new_field = models.ForeignKey(model, default=<existing model id here>)

3

内部に既にデータがあるテーブルへの参照を追加することはできません。
変化する:

user = models.OneToOneField(User)

に:

user = models.OneToOneField(User, default = "")

行う:

python manage.py makemigrations
python manage.py migrate

再度変更:

user = models.OneToOneField(User)

もう一度移行を行います。

python manage.py makemigrations
python manage.py migrate

2

new_fileにブールプロパティnullを追加します。

new_field = models.CharField(max_length=140, null=True)

を実行した後./manage.py syncdb、DBを更新します。そして最後にあなたは走り./manage.py makemigrations./manage.py migrate



2

テーブルにすでにデータベースエントリがありますUserProfileか?そうである場合、新しい列を追加するときに、DBはそれを設定できないため、何に設定すべきかわかりませんNULL。したがって、列のこれらのフィールドに何を設定するかを尋ねますnew_fields。問題を解決するには、このテーブルからすべての行を削除する必要がありました。

(私はこれが少し前に回答されたことを知っていますが、私はこの問題に遭遇しただけで、これが私の解決策でした。うまくいけば、これがこれを見た新しい人を助けるでしょう)


1
テーブルに行を挿入していませんが、まだこれを取得しています。Tomaszの提案に従い、すべての移行履歴を削除し、移行テーブルをクリアしてモデルを変更する必要があります。
WesternGun 2018年

1

私が正直に言うと、これを回避する最良の方法は、必要なすべてのフィールドを使用して少し異なる名前の別のモデルを作成することでした。移行を実行します。未使用のモデルを削除して、移行を再度実行してください。出来上がり。


1

問題のモデルのテーブルを切り捨てても問題がない場合はNone、プロンプトで1回限りのデフォルト値を指定できます。default=Noneコードにデフォルトがない場合、移行は不要になります。デフォルトを必要とするデータがテーブルに存在しないため、これは問題なく適用できます。


1

私は開発サイクルの初期だったので、これは誰にとってもうまくいかないかもしれません(しかし、なぜそれがうまくいかないのかわかりません)。

blank=True, null=Trueエラーが発生した列に追加しました。次に、python manage.py makemigrationsコマンドを実行しました。

このコマンドを実行した直後(およびを実行する前python manage.py migrate)に、blank=True, null=Trueすべての列からを削除しました。それから私はpython manage.py makemigrations再び走った。自分で選択した列を自分で変更するオプションが与えられました。

それから私は走りましたpython manage.py migrate、そして、すべてがうまくいきました!


0

Djangoが実際に言うのは:

Userprofileテーブルにはデータがnew_fieldあり、nullの値が存在する可能性がありますが、私は知りません。そうすると、nullのない値としてプロパティをマークしてもよろしいですか。

userprofileテーブルのどの値もNULL でないことが確実な場合-解放され、警告は無視されます。

このような場合のベストプラクティスは、オプション2に記載されているように、空の値を処理するRunPython移行を作成することです。

2)現時点では無視し、既存の行をNULLで処理します(たとえば、以前のデータ移行でNULL値を処理するためにRunPythonまたはRunSQL操作を追加したため)。

RunPythonの移行ではUserProfile、空のnew_field値を持つすべてのインスタンスを見つけ、そこに正しい値(またはDjangoがモデルに設定するように要求するデフォルト値)を配置する必要があります。あなたはこのようなものを得るでしょう:

# please keep in mind that new_value can be an empty string. You decide whether it is a correct value.
for profile in UserProfile.objects.filter(new_value__isnull=True).iterator():
    profile.new_value = calculate_value(profile)
    profile.save() # better to use batch save

楽しんで!


これがドキュメントのどこに書かれているかはわかりません。リンクを投稿していただけますか
コーディ

0

models.py

class UserProfile(models.Model): user = models.OneToOneField(User) website = models.URLField(blank=True) new_field = models.CharField(max_length=140, default="some_value")

デフォルトとしていくつかの値を追加する必要があります。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.