3

そこで、Djangoでアプリを開発していて、1.4バージョンの関数が必要だったので、更新することにしました。
しかし、私がやりたいと思ったときに奇妙なエラーが表示されsyncdb
ました。新しいmanage.pyものを使用しています。ご覧のとおり、いくつかのテーブルが作成されますが、失敗します。

./manage.py syncdb
Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_user_permissions
Creating table auth_user_groups
Creating table auth_user
Creating table django_content_type
Creating table django_session
Creating table django_site
Traceback (most recent call last):
  File "./manage.py", line 9, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/core/management/__init__.py", line 443, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/core/management/__init__.py", line 382, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/core/management/base.py", line 196, in run_from_argv
self.execute(*args, **options.__dict__)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/core/management/base.py", line 232, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/core/management/base.py", line 371, in handle
    return self.handle_noargs(**options)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/core/management/commands/syncdb.py", line 91, in handle_noargs
    sql, references = connection.creation.sql_create_model(model, self.style,     seen_models)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/django/db/backends/creation.py", line 44, in sql_create_model
    col_type = f.db_type(connection=self.connection)
TypeError: db_type() got an unexpected keyword argument 'connection'
4

2 に答える 2

3

同じ問題が発生しました。カスタムフィールドの定義に接続パラメーターがありませんでした。

from django.db import models

class BigIntegerField(models.IntegerField):
    def db_type(self, connection):
        return "bigint"
于 2012-11-27T00:48:19.450 に答える
0

すでに古く、回答して受け入れた質問ですが、カスタマイズされたタイプを使用しておらず、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のドキュメントも参照してください

Field.db_type(self、connection):

接続オブジェクトとそれに関連付けられた設定を考慮して、フィールドのデータベース列のデータ型を返します。

そして、この問題を解決するには、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
于 2014-01-22T14:10:22.613 に答える