2009-08-26 6 views
1

Я пытался изменить код AuditTrail так, чтобы он не копировал поля ForeignKey, а копировал связанное с ним поле (т. Е. Я не хочу, чтобы внешний ключ в моей таблице базы данных аудиторская модель).Django: AuditTrail & Lazy Relations

Я написал copy_field функцию, которая выглядит так:

def copy_field(field): 
    while(isinstance(field, models.OneToOneField, models.ForeignKey)): 
     field = field.rel.get_related_field() 
    if isinstance(field, models.AutoField): 
     f = models.IntegerField() 
    else: 
     f = copy(field) 
    #...snip some adjusting of fs attributes... 
    return f 

Этот код запускается, когда модель, которая имеет атрибут AuditTrail готов (через class_prepared сигнала).

Однако, это сталкивается с проблемами, когда ForeignKey связано с полем на модели, которая не была подготовлена ​​еще - get_related_field() вызов потерпит неудачу, потому что field.rel.to это строка, содержащая имя соответствующей модели, а не образцом модели.

Я нахожусь в недоумении, что делать, чтобы обойти это. Должен ли я определять, какие зависимости у модели есть, и ждать, пока они все подготовлены, прежде чем я начну копировать поля? Любые идеи о том, как лучше всего это сделать?

ответ

0

Что я на самом деле делал, это перечисление всех зависимостей, которые имела эта модель (путем определения пары canoncial app/name, копирования кода от django.db.models.fields.related, чтобы определить это) и изменение обработчика сигнала class_prepared для прослушивания всех моделей, а не просто моя целевая модель.

Когда обработчик распознал модель в моем списке зависимостей, она удалит ее из списка и проверит, был ли список пустым; Если бы это было так, то было бы хорошо создать модель аудита. Важное замечание заключалось в том, чтобы отключить обработчик class_prepared перед созданием модели, иначе я столкнулся с бесконечной рекурсией (в качестве альтернативы я мог бы лучше настроить обработчик).

dependencies = [] 
    for field in cls._meta.local_fields: 
     while isinstance(field, (models.OneToOneField, models.ForeignKey)): 
      if isinstance(field.rel.to,basestring): 
       dependencies.append(get_canonical(cls,field.rel.to)) 
       break 
      else: 
       field = field.rel.get_related_field() 

    def _contribute(sender, **kwargs): 
     key = (sender._meta.app_label, sender.__name__) 
     if key in dependencies: 
      dependencies.remove(key) 
     if not dependencies: 
      models.signals.class_prepared.disconnect(_contribute) 
      model = create_audit_model(cls) 

    models.signals.class_prepared.connect(_contribute, weak=False) 

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

  • Нет связанных вопросов^_^