Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django中的外键和保存方法_Django_Recursion_Foreign Keys_Save - Fatal编程技术网

Django中的外键和保存方法

Django中的外键和保存方法,django,recursion,foreign-keys,save,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) 在B中: def save(s

我有以下型号:

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)
在B中:

def save(self, *args, **kwargs):
  if self.a:
    self.a.save()
  super(B, self).save(*args, **kwargs)
这不起作用,即使在调用save()时为A.b和b.A分配了一个id,它仍然违反了A中的NOTNULL约束。 我在某个地方读到过,这是由于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)
这确实有效,但对于记录,这里有一个小助手,可以在保存之前自动清除缓存:

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)

好的,这取决于你先保存哪个对象,实际上在我的情况下,这两种情况都可能发生,但如果我能解决这个问题,那就太好了。。。这是正确的顺序,因为在保存时,我希望外键有效,因此必须先保存它。所以在我的例子中,我应该使用预保存信号,我尝试过,但它仍然会给我NOTNULL约束错误。