2012-12-07 80 views
3

我在Django中遇到了一些缓存问题。到目前为止,我只在运行测试套件时才看到这个问题。问题在于,有时候(这似乎总是在第二次调用代码时发生),Django不更新它的缓存,或者它变得不一致。在Django的ManyToManyField中缓存

与一些调试抽出代码是:

class Source(models.Model): 
    name = models.CharField(max_length = 50) 
    quality = models.IntegerField(default = 0) 

class Reference(models.Model): 
    url = models.URLField() 
    source = models.ForeignKey(Source) 

    class Meta: 
     ordering = ['-source__quality'] 

class Issue(models.Model): 
    references = models.ManyToManyField(Reference) 
    master = models.ForeignKey(Reference, related_name = 'mastered_issue_set') 

def auto_create(instance): 
    issue = Issue.objects.create(master = instance) 
    print issue.references.count(), issue.references.all() 
    issue.references.add(instance) 
    print issue.references.count(), issue.references.all() 

在第一次调用我正确地得到下面的输出:

0 [] 
1 [<Reference: test>] 

然而,在第二次调用到auto_create,Django的认为有一个参考,但它并没有给我:

0 [] 
1 [] 

这种行为当然会破坏更多的代码。任何想法在这里可能会出错或至少如何调试它?

PS:它看起来像订购Reference类是造成这种情况。但是我仍然不清楚为什么。

+0

你能指定'auto_create()'的参数吗? – Oleksiy

+0

这是一个''Reference''实例(新创建)。 –

回答

0

最后我发现是什么原因导致了这个问题。这是我自己的缓存代码,而不是Django的。

我曾在地方风俗源管理器,返回和缓存的一些标准来源:

class SourceManager(models.Manager): 
    url_source = None 
    def get_generic(self): 
     if self.url_source is None: 
      self.url_source, created = self.get_or_create(name = 'URL', quality = 0) 
     return self.url_source 

class Source(models.Model): 
    name = models.CharField(max_length = 50) 
    quality = models.IntegerField(default = 0) 

    objects = SourceManager() 

这工作在应用完全没有问题 - 一旦创建源,经理会记住它的存在为源不要改变他们的一生。然而,在测试中,当整个测试在单个事务中运行并且然后恢复时,它们消失。

我感到奇怪的是,models.ForeignKey没有抱怨越来越不存在的对象,但后来出现了错误,同时通过source__quality作为垫层排序JOIN SELECT找不到匹配Source对象。

0

我无法用sqlite3重现。难道传入的Reference实例没有保存?以下运行没有打嗝:

def auto_create(instance): 
    issue = Issue.objects.create(master = instance) 
    print issue.references.count(), issue.references.all() 
    assert issue.references.count()==0, "initial ref count is not null" 
    assert len(issue.references.all())==0, "initial ref array is not empty" 
    issue.references.add(instance) 
    print issue.references.count(), issue.references.all() 
    assert issue.references.count()==1, "ref count is not incremented" 
    assert len(issue.references.all())==1, "initial ref array is not populated" 


def test_auto(): 
    s = Source() 
    s.save() 
    r = Reference(source=s) 
    r.save() 
    auto_create(r) 
+0

如果不保存引用,那么''''issue.references.add(...)''将会失败。事实上,提取的代码不会暴露这个问题,我不能在这里发布整个项目,这太大了。我只是在寻找指针,在我的代码中可能会出错。使用真正的应用程序,我可以在SQLite和PostgreSQL后端上重现这些问题。 –