ヨ男、
。
まず、私は、新しいフィールドを作成しました:
from django.db.models.deletion import DO_NOTHING
from django.db.models.fields.related import ForeignKey, ManyToOneRel
class SoftForeignKey(ForeignKey):
"""
This field behaves like a normal django ForeignKey only without hard database constraints.
"""
def __init__(self, to, to_field=None, rel_class=ManyToOneRel, **kwargs):
ForeignKey.__init__(self, to, to_field=to_field, rel_class=rel_class, **kwargs)
self.on_delete = DO_NOTHING
no_db_constraints = True
私は私のデータベーススキーマを管理するために、南使用しているので、私はこれを追加する必要がありました:私は猿に持っていた、そして、
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], [r'^ecm\.lib\.softfk\.SoftForeignKey'])
をパッチ南は、no_db_constraints
パラメータを考慮に入れます。
from django.db.models.deletion import DO_NOTHING
from django.db.models.fields.related import ForeignKey, ManyToOneRel
from django.core.management.color import no_style
from south.db.generic import DatabaseOperations, invalidate_table_constraints, flatten
def column_sql(self, table_name, field_name, field, tablespace='', with_name=True, field_prepared=False):
"""
Creates the SQL snippet for a column. Used by add_column and add_table.
"""
# If the field hasn't already been told its attribute name, do so.
...
...
...
if field.rel and self.supports_foreign_keys:
# HACK: "soft" FK handling begin
if not hasattr(field, 'no_db_constraints') or not field.no_db_constraints:
self.add_deferred_sql(
self.foreign_key_sql(
table_name,
field.column,
field.rel.to._meta.db_table,
field.rel.to._meta.get_field(field.rel.field_name).column
)
)
# HACK: "soft" FK handling end
# Things like the contrib.gis module fields have this in 1.1 and below
if hasattr(field, 'post_create_sql'):
for stmt in field.post_create_sql(no_style(), ta
....
....
# monkey patch South here
DatabaseOperations.column_sql = column_sql
そして:
from django.db.models.deletion import DO_NOTHING
from django.db.models.fields.related import ForeignKey, ManyToOneRel
from django.core.management.color import no_style
from south.db.generic import DatabaseOperations, invalidate_table_constraints, flatten
@invalidate_table_constraints
def alter_column(self, table_name, name, field, explicit_name=True, ignore_constraints=False):
"""
Alters the given column name so it will match the given field.
Note that conversion between the two by the database must be possible.
Will not automatically add _id by default; to have this behavour, pass
explicit_name=False.
@param table_name: The name of the table to add the column to
@param name: The name of the column to alter
@param field: The new field definition to use
"""
if self.dry_run:
if self.debug:
...
...
if not ignore_constraints:
# Add back FK constraints if needed
if field.rel and self.supports_foreign_keys:
# HACK: "soft" FK handling begin
if not hasattr(field, 'no_db_constraints') or not field.no_db_constraints:
self.execute(
self.foreign_key_sql(
table_name,
field.column,
field.rel.to._meta.db_table,
field.rel.to._meta.get_field(field.rel.field_name).column
)
)
# HACK: "soft" FK handling end
# monkey patch South here
DatabaseOperations.alter_column = alter_column
これは本当に醜いですが、私は別の方法を見つけることができませんでしたFK制約の作成に関与する2つの機能がありました。
ここで、SoftForeignKeyフィールドは、参照整合性の適用がないことを除いて、通常のForeignKeyとまったく同じように使用できます。
は、完全な猿パッチについてはこちらをご覧ください:
それは本当に異種のキーではないのですか? –
まあ、db制約なしでdjango ForeignKeyのすべての機能を利用したいと思っています。 – Robin
たとえば、この 'SoftForeignKey'によって参照されるテーブルから行を削除するには、カスケードしたり、キーをNULLに設定する必要がありません。また、オブジェクトがターゲットテーブル内に存在しない行への参照を持つ場合、 'ObjectDoesNotExist'例外が発生します。しかし、私はデータベースがこの種の状態を受け入れるようにしたい。 – Robin