2012-01-14 15 views
2

私はこのコードhttp://djangosnippets.org/snippets/2283/を見つけましたが、別のモデル(キーワードスルー)を使用するmanytomanyfieldsでは機能しません - マージしようとするとAttributeErrorが発生します。Django 1.3で重複をマージする最も良い方法は?

この方法やオブジェクトをマージする別の方法を修正する方法はありますか?

編集:詳細

Iは、3つのモデルを持っている:A、B、C

Aは、多対多フィールドを有するIからのコードを実行するB.

介してCを指し、 "m2mfield"ジャンゴスニペット、それは言う例外

'ManyRelatedManager' object has no attribute 'remove' 

私は、これはDjangoのソース(django.db.models.fields.related.pyライン499)でのコメントとは何かを持っていると思うと失敗します:

# If the ManyToMany relation has an intermediary model, 
# the add and remove methods do not exist. 

私が得たコードスニペットは、ManyToManyリレーションシップと中間モデルとの間に何の違いもないと思います。だからこそ私は、コードや、私が望む(合併する)ことを達成するための別の方法を修正する何らかの方法を探しています。

+1

あなたはおそらく関与モデルのためのサンプルを提供し、より詳細に問題を記述することができますか? –

+0

あなたがしたことを示し、何がうまくいかなかったかを示します(トレースバック)。これらは、問題を伝える良い第一歩です。 –

+0

私はいくつかの詳細で私の質問を更新しました。私は何が間違っているのか分かったと思うが、それをどう働かせるか分からない... – Weier

答えて

2

最終的に、ManyToManyフィールドのケースを処理するコードを変更しました。ここ は変更されるものです:

# Migrate all many to many references from alias object to primary object. 
for related_many_object in alias_object._meta.get_all_related_many_to_many_objects(): 
    alias_varname = related_many_object.get_accessor_name() 
    obj_varname = related_many_object.field.name 

    # Treatment depends on if the many_to_many field is created through another model 
    if getattr(alias_object, alias_varname).through._meta.auto_created: 
     if alias_varname is not None: 
      # standard case 
      related_many_objects = getattr(alias_object, alias_varname).all() 
     else: 
      # special case, symmetrical relation, no reverse accessor 
      related_many_objects = getattr(alias_object, obj_varname).all() 
     for obj in related_many_objects.all(): 
      getattr(obj, obj_varname).remove(alias_object) 
      getattr(obj, obj_varname).add(primary_object) 
    else: 
     related_many_objects = getattr(alias_object, alias_varname).all() 

     through_model = getattr(alias_object, alias_varname).through 
     through_field_name = None 
     for f in through_model._meta.fields: 
      if isinstance(f, ForeignKey): 
       if f.rel.to == primary_class : 
       # f is the field in our 'through' model which points to an instance of primary_class 
        through_field_name = f.name 

     for obj in related_many_objects.all(): 
      kwargs = { 
       through_field_name: obj, 
      } 
      for through_obj in through_model.objects.filter(**kwargs): 
       setattr(through_obj, through_field_name, primary_object) 
       through_obj.save() 
0

エラーは、作成しようとしているmanytomanyフィールドがスルーモデルで管理されていることを意味します。スニペットであり

がマージが機能するためには意識したモデルを通じてでなければならないコードを貼り付け、それはL55が開始:

# Migrate all many to many references from alias object to primary object. 
    for related_many_object in alias_object._meta.get_all_related_many_to_many_objects(): 
     alias_varname = related_many_object.get_accessor_name() 
     obj_varname = related_many_object.field.name 

     if alias_varname is not None: 
      # standard case 
      related_many_objects = getattr(alias_object, alias_varname).all() 
     else: 
      # special case, symmetrical relation, no reverse accessor 
      related_many_objects = getattr(alias_object, obj_varname).all() 
     for obj in related_many_objects.all(): 
      getattr(obj, obj_varname).remove(alias_object) 
      getattr(obj, obj_varname).add(primary_object) # this can't work 

あなたはmerge_model_objects機能の辞書を提供する必要がどこmerge_model_objectsはなりますスルークラスを構築する関数を選択することができます。このコードは、私が上で取ったスニペットの最後の行を置き換えなければならないでしょう。

しかし、A1、A2、C1、C2は同じであるが、B1、B2は同じではなく、現在のコードでも処理されないようにする必要があります。

+0

実際には、モデルを通してケースを処理するためにコードを後で修正した: – Weier

+0

@トーマスは質問を閉じるか、自分自身の解決策、やる気。 – amirouche

関連する問題