2012-01-14 2 views
2

Я нашел этот код http://djangosnippets.org/snippets/2283/, но я думаю, что он не работает с manytomanyfields, которые используют другую модель (ключевое слово через) - я получаю AttributeError при попытке слияния.Лучший способ объединить дубликаты в Django 1.3?

Вы знаете какой-либо способ исправить тот или иной метод слияния объектов?

Edit: Подробнее

У меня есть 3 модели: A, B, C

А имеет manytomany поле "m2mfield", указывающий на C через B.

Когда я запускаю код из Джанго фрагменты, она не за исключением

'ManyRelatedManager' object has no attribute 'remove' 

Я думаю, что это что-то делать с комментарием в источнике Джанго (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

@Thomas закрыть вопрос или дать сам решение, танский. – amirouche

Смежные вопросы