すでに古く、回答して受け入れた質問ですが、カスタマイズされたタイプを使用しておらず、Django Evolutionエラー(syncdbではない)であるため、理解を追加していますevolve --hint --execute
。将来誰かに役立つかもしれないと思います。。
私はPythonは平均的で、Djangoは初めてです。既存のプロジェクトにいくつかの新しい機能を追加したときにも、同じ問題が発生します。新しい機能を追加するにはmodels.CharField()
、次のように、タイプの新しいフィールドをいくつか追加する必要がありました。
included_domains = models.CharField(
"set of comma(,) seprated list of domains in target emails",
default="",
max_length=it_len.EMAIL_LEN*5)
excluded_domains = models.CharField(
"set of comma(,) seprated list of domains NOT in target emails",
default="",
max_length=it_len.EMAIL_LEN*5)
私が使用しているDjangoのバージョンは1.3.1です:
$ python -c "import django; print django.get_version()"
1.3.1 <--------# version
$python manage.py syncdb
Project signature has changed - an evolution is required
Django Evolution: Django Evolutionは、Djangoの拡張機能であり、モデルの変更を経時的に追跡し、それらの変更を反映するようにデータベースを更新できます。
$ python manage.py evolve --hint
#----- Evolution for messagingframework
from django_evolution.mutations import AddField
from django.db import models
MUTATIONS = [
AddField('MessageConfiguration', 'excluded_domains', models.CharField, initial=u'', max_length=300),
AddField('MessageConfiguration', 'included_domains', models.CharField, initial=u'', max_length=300)
]
#----------------------
Trial evolution successful.
Run './manage.py evolve --hint --execute' to apply evolution.
裁判はサスでした、そして私がDBに変更を適用しようとしたとき
$ python manage.py evolve --hint --execute
Traceback (most recent call last):
File "manage.py", line 25, in <module>
execute_manager(settings)
File "/var/www/sites/www.taxspanner.com/django/core/management/__init__.py", line 362, in execute_manager
utility.execute()
File "/var/www/sites/www.taxspanner.com/django/core/management/__init__.py", line 303, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/var/www/sites/www.taxspanner.com/django/core/management/base.py", line 195, in run_from_argv
self.execute(*args, **options.__dict__)
File "/var/www/sites/www.taxspanner.com/django/core/management/base.py", line 222, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python2.7/dist-packages/django_evolution-0.6.9.dev_r225-py2.7.egg/django_evolution/management/commands/evolve.py", line 60, in handle
self.evolve(*app_labels, **options)
File "/usr/local/lib/python2.7/dist-packages/django_evolution-0.6.9.dev_r225-py2.7.egg/django_evolution/management/commands/evolve.py", line 140, in evolve
database))
File "/usr/local/lib/python2.7/dist-packages/django_evolution-0.6.9.dev_r225-py2.7.egg/django_evolution/mutations.py", line 426, in mutate
return self.add_column(app_label, proj_sig, database)
File "/usr/local/lib/python2.7/dist-packages/django_evolution-0.6.9.dev_r225-py2.7.egg/django_evolution/mutations.py", line 438, in add_column
sql_statements = evolver.add_column(model, field, self.initial)
File "/usr/local/lib/python2.7/dist-packages/django_evolution-0.6.9.dev_r225-py2.7.egg/django_evolution/db/common.py", line 142, in add_column
f.db_type(connection=self.connection), # <=== here f is field class object
TypeError: db_type() got an unexpected keyword argument 'connection'
この例外を理解するために、この例外が次のようなものであることを確認します。
>>> def f(a):
... print a
...
>>> f('b', b='a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() got an unexpected keyword argument 'b'
>>>
そのため、関数のシグネチャが変更されました。
新しいカスタマイズフィールドまたは列挙フィールドを追加していませんが、このエラーが発生した場合でも、ほとんどのデータベース(PostgreSQLを使用しています)でサポートされているのは、すでにmodelおよびchar型フィールドにある2つの類似フィールドのみです。
それから私は@から読みました:ラッセルキース-マギー-4返信。
ここでヒットしたのは、複数のデータベースをサポートしないコードの非推奨サイクルの終わりです。
Django 1.2では、複数のデータベースサポートが導入されました。これをサポートするために、とのプロトタイプget_db_preb_lookup()
が
get_db_prep_value()
変更されました。
下位互換性のために、開発者によってまだ修正されていない場合にこれらのメソッドを透過的に「修正」するシムを追加しました。
Django 1.2では、これらのシムを使用すると、PendingDeprecationWarningが発生しました。Django 1.3では、DeprecationWarningが発生しました。
Django 1.4では、shimコードが削除されたため、更新されなかったコードでは、説明したようなエラーが発生するようになりました。
しかし、Django Evolutionの新しいバージョンが原因で、DeprecationWarning警告が表示されません。
しかし、上記の引用から、複数のデータベースをサポートするために関数シグネチャが追加され、追加の引数connection
が必要であることが理解できました。またdb_type()
、Djangoのインストールで署名を次のように確認します。
/django$ grep --exclude-dir=".svn" -n 'def db_type(' * -R
contrib/localflavor/us/models.py:8: def db_type(self):
contrib/localflavor/us/models.py:24: def db_type(self):
:
:
Djangoのドキュメントも参照してください
接続オブジェクトとそれに関連付けられた設定を考慮して、フィールドのデータベース列のデータ型を返します。
そして、この問題を解決するには、models.filed
クラスを継承してdef db_type()
関数を上書きする必要があることを理解できました。また、300文字のタイプフィールドを作成するPostgreSQLを使用しているため、を返す必要があり'char(300)'
ます。私のmodels.pyに追加しました:
class CharMaxlengthN(models.Field):
def db_type(self, connection):
return 'char(%d)' % self.max_length # because I am using postgresql
同様の問題が発生した場合は、作成する必要のある列のタイプをアンダースコアDBのマニュアルで確認し、文字列を返します。
そして、新しいフィールドの定義を変更しました(私が追加する必要があります)コメントを読んでください:
included_domains = CharMaxlengthN( # <--Notice change
"set of comma(,) seprated list of domains in target emails",
default="",
max_length=it_len.EMAIL_LEN*5)
excluded_domains = CharMaxlengthN( # <-- Notice change
"set of comma(,) seprated list of domains NOT in target emails",
default="",
max_length=it_len.EMAIL_LEN*5)
次に、以前に失敗したのと同じコマンドを実行しました。
t$ python manage.py evolve --hint --execute
You have requested a database evolution. This will alter tables
and data currently in the None database, and may result in
IRREVERSABLE DATA LOSS. Evolutions should be *thoroughly* reviewed
prior to execution.
Are you sure you want to execute the evolutions?
Type 'yes' to continue, or 'no' to cancel: yes
Evolution successful.
また、DBをチェックし、新しく追加された機能をテストしました。これで完全に機能し、DBの問題は発生しません。
ENUMフィールドを作成する場合は、を読み取りますSpecifying a mySQL ENUM in a Django model
。
編集:サブクラス化の代わりに、models.Field
より具体的なサブクラスを継承する必要があることに気づきましたmodels.CharField
。
同様に、Decimal DBフィールドを作成する必要があるため、モデルに次のクラスを追加しました。
class DecimalField(models.DecimalField):
def db_type(self, connection):
d = {
'max_digits': self.max_digits,
'decimal_places': self.decimal_places,
}
return 'numeric(%(max_digits)s, %(decimal_places)s)' % d