Python 3、Django 1.8.5、Postgres
正常に動作しているモデルSites
があります。私は最近、airport_codeフィールドを追加して、データを移行しようとしました。
class Site(BaseModel):
objects = SiteManager()
name = models.CharField(max_length=200, unique=True)
domain = models.CharField(max_length=200, unique=True)
weather = models.CharField(max_length=10)
nearby_sites = models.ManyToManyField('self', symmetrical=False, blank=True)
users = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True)
facebook = models.URLField(max_length=200)
Twitter = models.URLField(max_length=200)
header_override = models.TextField(blank=True)
email_header_override = models.TextField(blank=True)
timely_site_tag_id = models.IntegerField()
timely_featured_tag_id = models.IntegerField()
timely_domain = models.CharField(max_length=255)
sitemap_public_id = models.CharField(max_length=255)
state = models.CharField(max_length=24)
airport_code = JSONField()
しかし、makemigrations
を実行するとエラーが発生しました。
Django.db.utils.ProgrammingError: column sites_site.airport_code does not exist LINE 1: ..._site"."sitemap_public_id", "sites_site"."state", "sites_sit...
もちろん、これは意味がありません。マイグレーション内で列を作成しようとしているときに、列が明らかに存在しないためです。
スタックオーバーフローに関するこのバグについて、未回答の質問を多数見かけたり、移行ファイルを手動で作成したり、データベースを破棄して再構築したりするための解決策があります。これは大丈夫な解決策ではありません。
このバグは、settings.pyのINSTALLED_APPSからDjangoデバッグツールバーをコメントアウトすることで解決されました。デバッグツールバーが原因である理由はわかりませんが、コメントアウトした後、 makemigrations
およびmigrate
を問題なく実行します。
私がそれを理解しようと12時間費やしたので、これが誰かを助けることを願っています。
Makemigrationsを実行した後、必ずスタックトレースを1つずつ実行してください。
私の場合、まったく異なるアプリのforms.pyに含まれているFormへの呼び出しを介してトレースされていることに気付きました。たまたま、新しい移行を作成しようとしているモデルへの呼び出しがありました。
Formクラスをforms.pyからviews.pyに移動すると、問題が修正されました。
私の場合は、unique_together制約が設定されていたためです。
フィールドを削除したい場合、自動生成された移行では、unique_together制約を削除する前にフィールドを削除しようとしました。
私がしなければならなかったのはマイグレーションファイル内のmigrations.AlterUniqueTogether制約を手動で上に移動するなので、Djangoは、フィールドを削除する前にまず制約を削除します。
これが誰かの役に立つことを願っています。
私もこの問題に遭遇し、@ Nexusの回答が役に立ちました。問題の原因をより明確に説明するために、ここで特定のケースの詳細を提供すると思いました。私には潜在的なバグのようです。
次のようなモデルBrand
があります。
class Brand(BaseModelClass):
name = CharField(max_length=256, unique=True)
website = ForeignKey(URL, on_delete=CASCADE, null=True, blank=True)
私はpython manage.py makemigrations
Boolean
フィールドを次のように追加した後:
class Brand(BaseModelClass):
name = CharField(max_length=256, unique=True)
website = ForeignKey(URL, on_delete=CASCADE, null=True, blank=True)
trusted = Boolean(default=True)
makemigrations
コマンドを実行すると、OPと同様のエラーを受け取りました。
Django.db.utils.ProgrammingError: column appname_brand.trusted does not exist
@Nexus 'の提案に従い、Djangoの主要な問題ではないと想定して、スタックトレースを1行ずつ実行しました。結局のところ、アプリの1つでforms.py
ファイル次のものを用意しました。
choices={(str(brand.id), brand.name) for brand in Brand.objects.all()}
解決策は、その行を単にコメント化してmanage.py makemigrations
、次にmanage.py migrate
。その後、その行のコメントを外し、すべての機能とフォームの機能は以前と同じように機能しました。
Postgresデータベースを別のサーバーに移行した後で、この問題が発生します。どういうわけか私はデータベースをめちゃくちゃにし、新しいクラスUserProfileでモデルを更新できませんでした。
既存のスキーマの初期移行を作成する問題を解決しました:
Django_migrations
テーブルを空にします:delete from Django_migrations;
コマンドでDELETE FROM Django_migrations WHERE app='my_app';
migrations
フォルダを削除します:rm -rf <app>/migrations/
python manage.py migrate --fake
python manage.py makemigrations <app>
。依存関係に注意してください(ForeignKeyを含むモデルは、親モデルの後に実行する必要があります)。python manage.py migrate --fake-initial
ここにそれを手に入れました: https://stackoverflow.com/a/2989848
PSこれが問題の解決に関連していたかどうかはわかりませんが、最初に、エラーを引き起こしたpostgresqlのテーブルを削除し、モデルのUserProfileクラスをコメント化しました。
シェル:
Sudo -su postgres
psql databse_name
DROP TABLE table_name;
models.py:
#class UserProfile(models.Model):
#user = models.OneToOneField(settings.AUTH_USER_MODEL, unique=True, primary_key=True, on_delete=models.CASCADE, related_name='user_profile')
#avatar = ThumbnailerImageField(upload_to='profile_images', blank=True)
#country = models.CharField(max_length = 128)
同じ問題(列が存在しない)が発生しましたが、migrate
ではなくmakemigrations
を実行しようとすると
原因:最後の変更の移行を実行する前に、移行ファイルを削除し、それらを単一の偽の初期移行ファイル0001に置き換えました
解決:
Django_migrations
から、そのアプリの移行を担当する行を削除します。これは、Django=どの移行が適用され、どの移行がまだ適用される必要があるかを知る方法です。そして、これがこの問題をどのように解決するかです:
postgresユーザーとしてログインします(私のユーザーはposgresと呼ばれます):
Sudo -i -u postgres
SQLターミナルを開き、データベースに接続します。
psql -d database_name
テーブルを一覧表示し、そのアプリに関連するテーブルを見つけます。
\dt
それらをドロップします(関係のあるドロップ順序を考慮してください)。
DROP TABLE tablename ;
id |アプリ|名前|適用された
-+ ------ + -------- + --------- +
SELECT * FROM Django_migrations;
そのアプリの移行の行を削除します(IDまたはアプリごとに削除できます。アプリでは「引用符」を忘れないでください)。
DELETE FROM Django_migrations WHERE app='your_app';
ログアウトしてマイグレーションを実行します(場合によってはmakemigrationsを実行します)。
python manage.py migrate --settings=your.settings.module_if_any
注:場合によっては、そのアプリのすべてのテーブルを削除する必要はなく、すべての移行を削除する必要はありません。問題を引き起こしているモデルのテーブルのみを削除する必要があります。
これがお役に立てば幸いです。
Django 1.11にアップグレードした後、この問題に遭遇しました。この問題に恒久的に対処したかったので、テーブルで移行を実行するたびにコードをコメント/コメント解除する必要はありません。私のアプローチ:
from Django.db.utils import ProgrammingError as AvoidDataMigrationError
try:
... do stuff that breaks migrations
except AvoidDataMigrationError:
pass
インポート中の例外の名前をAvoidDataMigrationError
に変更したので、例外が存在する理由は明らかです。
必要なフィールドを実際に含むようにSingletonModelを移行しようとしたときに、今ちょうど同じエラーが発生しました。
エラーの理由は、モデルAがこのSingletonModelのいくつかのフィールドを(構成可能な値として)使用したことです。また、移行プロセス中のモデルAのインスタンス化中に、私の移行が安全であることを保証することはできませんでした。
同僚には素晴らしいアイデアがありました。フィールドのデフォルト値を関数呼び出しにし、そのために遅延させます。
例:
class A (models.Model):
default_value = models.DecimalField(default: lambda: SingletonModel.get_solo().value, ...)
そのため、私のアドバイス:問題のある呼び出し(スタックトレースに表示されます)を遅延呼び出しにしてみてください。
パーティーに遅れましたが、共有したい情報がいくつかあります。とても助かりました! :)
Django-solo を使用してアプリの構成をデータベースに保存していますが、構成モデルに新しいフィールドを追加すると、Alexと同じ問題が発生しました。 Stacktraceは、データベースから構成を取得している行を示しました:conf = SiteConfiguration().get_solo()
。
GithubのDjango-soloプロジェクトには 終了した問題 があります。アイデアは、モデルの読み込みを遅延させることです(MrKickkillerが以前指摘したとおり)。
したがって、モダンDjangoバージョン(私の場合は3.0))の場合、このコードは完全に機能します。
from Django.utils.functional import SimpleLazyObject
conf = SimpleLazyObject(SiteConfiguration.get_solo)
アプリケーションをロードするときにクエリを実行していないことを確認してください!など。に:
class A:
field = fn_that_makes_query()
migrate
またはmakemigrations
を実行すると、Djangoはアプリケーション全体をロードするシステムチェックを実行するため、このプロセス中に追加/変更されたクエリを使用すると、まだ存在しないdbフィールドにアクセスしようとしているため、矛盾が発生するdbフィールド。
最近この問題に巻き込まれました。
私の場合、コードに存在しないフィールドへの参照を追加してから、モデルファイルにアクセスして新しいフィールドを追加し、上記のエラーをスローするmakemigrations
コマンドを実行しようとしました。
そのため、スタックトレースを最後まで調べたところ、新しく追加された参照が問題であることがわかりました。とコメントし、makemigrations
とvoilaを実行しました。
私は同じ問題を抱えています、これが私のケースです:アプリでMyApp
モデルに新しいフィールドを追加します:
class Advisors(models.Model):
AdvID = models.IntegerField(primary_key=True)
Name = models.CharField(max_length=200,null=False)
ParentID = models.IntegerField(null=True) # <--- the NEW field I add
だから私がしたことは:urls.py
of MyProject
、NOT MyApp
、MyApp
にリンクされたurl()をコメント化して、makemigrations
を実行し、migrate
はすべて実行されます上手; MyApp/urls.py
ファイル:
urlpatterns = [
url(r'^admin/', admin.site.urls, name='admin'),
url(r'^$', views.HomePage.as_view(),name='home'),
#comment out the following line, after migrate success, bring it back;
# url(r'^myapp/', include('myapp.urls',namespace='research')), <---
]
私の場合、カスタムAdminSite
がMyModel.objects.filter
アプリケーションstart
で、makemigrations
およびmigrate
データベースに対してそれを無効にしました。
私もpython manage.py makemigrations app1
のようなコマンドを実行したときに同じ問題が発生しました。ビューの下で別のapp2で実行されているカスタムormsにコメントすることで問題を解決しました。
例:
inside app1models.py
class ModelA(models.Model):
subject = models.CharField(max_length=1)
course = models.CharField(max_length=1)
inside app2view.py
# obj = ModelA.object.all()
# get_subjct = [s.subject for s in obj]
だからここで私は上記のコードにコメントし、makemigrationsを実行して移行してからコメントを外しました。
正常に動作しています...