django - Django 中的外键和保存方法

标签 django recursion foreign-keys save

我有以下型号:

class A:
  b = ForeignKey('B')

class B:
  a = ForeignKey('A', null=True)

我有几种方法可以解码 json 对象并创建对象 A 和 B 的树。
假设我有一个要保存的 A 类型的对象,我正在尝试编写这样的内容

在 A 类中:
def save(self, *args, **kwargs):
  self.b.save()
  super(A, self).save(*args, **kwargs)

在乙:
def save(self, *args, **kwargs):
  if self.a:
    self.a.save()
  super(B, self).save(*args, **kwargs)

这不起作用,即使 A.b 和 B.a 在调用 save() 时被分配了一个 id,它仍然违反了 A 中的非空约束。
我在某处读到这是由于 ORM 的工作方式以及对象如何以某种方式缓存。

提出的解决方案是做这样的事情:
a = A()
b = B()
b.save()
a.b = b
a.save()

但是由于递归的明显原因,这对我来说是不合适的。所以我能想到的唯一解决方法是为每个对象提供一个方法,该方法递归检索每个需要保存的对象,然后执行 for 循环以正确的顺序保存每个对象。我真的很想避免这种情况,因为当然实际模型更复杂,并且涉及两个以上的类,每个类有一个以上的外键。

所以我想我的问题很简单:在这种情况下有没有更好的方法或更常见的方法来处理?

最佳答案

经过一番深思熟虑后,我发现这确实是一个缓存“问题”。我没有时间查看 django 代码来了解事情的真正运作方式,所以如果有人有一些有趣的见解,那就太好了。

同时,我找到的解决方案是强制对象像这样清除其缓存:

def save(self, *args, **kwargs):
  self.b.save()
  self.b = self.b # yes ...
  super(A, self).save(*args, **kwargs)

这确实有效,但为了记录,这里有一个小 helper ,可以在任何保存之前自动清除缓存:
def clear_cache(obj):
  map(lambda x: obj.__setattr__(x, obj.__getattribute__(x)), \ # force reassignment
    map(lambda x: re.match('_(.*)_cache', x).groups()[0], \    # get attribute name
    filter(lambda x: x.find('_cache') != -1, dir(obj))))       # get all attribute with cache

@receiver(pre_save)
def cache_callback(sender, instance, **kwargs):
  clear_cache(instance)

关于django - Django 中的外键和保存方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7373772/

相关文章:

python - Django:如何更改内联表单集中的字段小部件

java - 如何测试一个集合是否包含该集合中其他两个数字的和

recursion - 为什么 reduce 会在 Clojure 中给出 StackOverflowError?

sql-server - sql :need to change constraint on rename table?

mysql - 错误代码 : 1822. 添加外键约束失败。缺少约束索引

MySQL:损坏的外键实现?

Django:在 forms.py clean 函数中访问请求

python - 无法从 django 连接到 mysql 将验证模型

jquery - 在一页上显示多个依赖的Python模型

c - 递归计数