2

djangoでデータベースレベルのデフォルトを設定するためにどのような方法を使用しますか?

これはdjangoのwontfix決定であることは理解していますが、特定のバックエンド(postgres)用に作成された場合、これを実装する方法についていくつかのアイデアが浮かんでいるはずです。

Pythonを介してこれを強化したいので、/sql/.sqlファイルを使用したくない。

次のような既存のフィールドに属性を設定する可能性があると考えていました。

foo = models.CharField(max_length=256, blank=True)
foo.db_default = ''

次に、フィールドをフィルタリングしてALTER COLUMN SET DEFAULTクエリを作成します。

どこに置けばいいの?ドキュメントは、post_syncdbフック内のデータベースを変更しないように言っています。

この行動をどこに置くべきか考えはありますか?sql/.sqlまた、ファイルを動的に生成できると考えています。管理コマンドは、何もないよりはましです。自動は素晴らしいでしょう。post_syncdbうーん、実行に間に合うようにSQLファイルを生成できるかどうか疑問に思いますか?テストします。

4

1 に答える 1

0

やってみpost_syncdbましたが、.sqlファイルを使うには遅すぎました。class_preparedに夢中になるのは間に合いましsyncdbたが、私は物事を複雑にしすぎていることに気づきました。モデルのインスタンス化時にコードを1回実行したほうがよいでしょう。

もう一度これをいじる必要があるとき、私は6か月で簡単に理解できる簡単な解決策に行き着きました。

def db_default(field, db_default):
    """
    Set attribute __db_default for signal to set default values with.
    """
    field.__db_default = db_default
    return field

class OrderShipLog(models.Model):
    date = db_default(models.DateTimeField(), 'now()')

def generate_default_sql(model):
    """
    Generate SQL for postgresql_psycopg2 default values because the shipping
    database post doesn't guarantee posting certain fields but id like them all to be strings.
    """
    db_fields = filter(lambda x: hasattr(x, '__db_default'), model._meta.fields)
    db_table = model._meta.db_table
    modelname = model._meta.object_name

    sql_dir = os.path.join(os.path.dirname(__file__), 'sql/')
    sql_filename = os.path.join(sql_dir, '{modelname}.postgresql_psycopg2.sql'.format(
        modelname=modelname.lower()))

    from django.db import connection
    if not db_table in connection.introspection.table_names():
        print >> sys.stderr, "{0} not in introspected table list; creating db default sql file : {1}".format(db_table, sql_filename)
        try:
            if not os.path.exists(sql_dir):
                os.makedirs(sql_dir)

            with open(sql_filename, 'w+') as f:
                for field in db_fields:
                    attname, db_column = field.get_attname_column()
                    if not field.__db_default:
                        raise Exception("Must enter value for field {modelname}.{field}.__db_default".format(
                            modelname=modelname,
                            field=attname))
                    f.write('ALTER TABLE {db_table} ALTER COLUMN {db_column} SET DEFAULT {default};\n'.format(
                        db_table=db_table,
                        db_column=db_column,
                        default=field.__db_default,
                        ))
        except Exception, e:
            print >> sys.stderr, "Could not generate SQL file. Manually set the defaults! {0}\n".format(e) * 10

generate_default_sql(OrderShipLog)
于 2012-06-07T03:18:17.583 に答える