1

我一直在尝试修改AuditTrail代码,使其不复制ForeignKey字段,而是复制相关字段(即,我不希望我的数据库表上的审计模型有外键)。

我写了一个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但是,当 a与尚未准备好的模型上的字段相关时,这会遇到问题-get_related_field()调用将失败,因为field.rel.to是包含相关模型名称的字符串,而不是模型实例。

我不知道该怎么做才能解决这个问题。在我开始复制字段之前,我是否必须确定模型具有哪些依赖项,并等到它们都准备好?关于解决此问题的最佳方法的任何想法?

4

1 回答 1

0

我最终要做的是列出模型所具有的所有依赖项(通过确定规范的应用程序/名称对;从中复制一些代码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)
于 2009-09-02T07:19:57.683 回答