代码之家  ›  专栏  ›  技术社区  ›  Wogan

Django:试听和懒惰关系

  •  1
  • Wogan  · 技术社区  · 15 年前

    我一直在尝试修改 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 信号)。

    但是,当 外星钥匙 与模型上尚未准备好的字段相关- get_related_field() 呼叫将失败,因为 field.rel.to 是包含相关模型的名称的字符串,而不是模型实例。

    我不知道该怎么做才能解决这个问题。在我开始复制字段之前,是否必须确定模型具有哪些依赖关系,并等到它们都准备好为止?有没有什么好办法?

    1 回复  |  直到 15 年前
        1
  •  0
  •   Wogan    15 年前

    我最终做的是列出模型的所有依赖项(通过确定一个规范的应用程序/名称对;从 django.db.models.fields.related 确定)并修改 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)