3

カスタム モデル マネージャーを構築しようとしていますが、エラーが発生しました。コードは次のようになります。

class LookupManager(models.Manager):
    def get_options(self, *args, **kwargs):
        return [(t.key, t.value) \
                for t in Lookup.objects.filter(group=args[0].upper())]


class Lookup(models.Model):
    group = models.CharField(max_length=1)
    key = models.CharField(max_length=1)
    value = models.CharField(max_length=128)
    objects = LookupManager()

(私は、結果をフィルタリングするために、さまざまな方法をget_options使用して遊んでいます)super()

を実行するsyncdbと、次のエラーが表示ops_lookupされます (対応するテーブルです)。

django.db.utils.DatabaseError: no such table: ops_lookup

[]マネージャーをフィルターの代わりに返すように変更すると、機能することに気付きましたsyncdb。また、実行syncdbしてすべてのテーブルが存在する場合は、コードを上記のように変更しても機能します。

syncdb初めて実行するときに、このテーブルが存在することを Django に期待させないようにするにはどうすればよいですか?

更新 トレースバックを調べた後、何が起こっているのかわかりました。ルックアップ テーブルは、他のテーブルのいくつかの列の選択肢を設定する値を含むことを意図しています。ルックアップテーブルが作成される前に、他のテーブルが作成されるときにマネージャーが呼び出されると思います。

Django に最初にルックアップ テーブルを作成させる方法はありますか (名前を変更する以外に?)

4

1 に答える 1

0

何が起こっているかというと、モジュールのロード時にデータベースにアクセスしようとしているということです。例えば:

class MyModel(models.Model):
    name = models.CharField(max_length=255)


class OtherModel(models.Model):
    some_field = models.CharField(
        max_length=255,
        # Next line fails on syncdb because the database table hasn't been created yet
        # but the model is being queried during module load time (during class definition)
        choices=[(o.pk, o.name) for o in MyModel.objects.all()]
    )

これは、あなたが述べたように、manager メソッドを (推移的に) 使用して他のモデルの選択肢を生成しているため、あなたがしていることと同じです。

リスト内包表記をジェネレーター式に置き換えると、イテラブルが返されますが、フィルター処理されたクエリセットは最初の反復まで評価されません。したがって、これにより上記の例が修正されます。

choices=((o.pk, o.name) for o in MyModel.objects.all())

あなたの例を使用すると、次のようになります。

class LookupManager(models.Manager):
    def get_options(self, *args, **kwargs):
        return ((t.key, t.value) for t in Lookup.objects.filter(group=args[0].upper()))

(( andの)代わりに[andを使用することに注意してください]) (外側のもの) - これは、ジェネレータ式を作成するための構文です。

于 2013-03-27T04:08:18.290 に答える