如何避免在Django循环中多次访问数据库?

问题描述:

目前,这个代码似乎要在每次循环迭代时发送到数据库(Postgres)两到四次。首先获取(并创建)Type,然后获取(并创建)Component。有没有办法在更少的数据库旅程中做到这一点?如何避免在Django循环中多次访问数据库?

models.py

class Component(models.Model): 
    long = models.TextField() 
    type = models.SmallForeignKey('Type', models.CASCADE) 


class Type(models.Model): 
    type = models.TextField(unique=True) 


class Point(models.Model): 
    components = models.ArrayField(models.IntegerField(), default=[]) 

    def save_components(self, geocode): 
     _components = [] 
     for c in geocode: 
      ct = Type.objects.get_or_create(type=c['types'][0]) 
      _components.append(Component.objects.get_or_create(long=c['long_name'], type=ct).pk) 
     self.components = _components 
     self.save() 

传入数据:

geocode = [ 
    { 
     "long_name" : "Luray", 
     "types" : [ "locality", "political" ] 
    }, 
    { 
     "long_name" : "Page County", 
     "types" : [ "administrative_area_level_2", "political" ] 
    }, 
    { 
     "long_name" : "Virginia", 
     "types" : [ "administrative_area_level_1", "political" ] 
    }, 
    { 
     "long_name" : "United States", 
     "types" : [ "country", "political" ] 
    } 
] 
+0

OK,'ct'和'组件'不是从哪里冒出来的,它们都是从数据库中提取出来的,你怎么不能触及数据库并获取信息呢? –

+0

@ShangWang我想应该可以在本地缓存,但这不是问题。目标是减少旅行次数,可能会减少到1或2次。我怀疑这是可能的,因为在第一次旅行时所有的信息已经存在。 – dtgq

+1

为什么你要存储一个主键数组,而不是使用ManyToManyField? –

很多的时候,Django的做一个体面的工作缓存数据库结果。如果你想有更多的控制,你可以做这样的事情(前提是你没有太多的类型)

 
class Point(models.Model): 
    components = models.ArrayField(models.IntegerField(), default=[]) 

    def save_components(self, geocode): 
     _components = [] 
     _types = {t.type: t for t in Type.objects.all()} 
     for c in geocode: 
      ct = _types.get(c['types'][0], None) 
      if not ct: 
       ct = Type.objects.create(type=c['types'][0]) 
      _components.append(Component.objects.get_or_create(long=c['long_name'], type=ct).pk) 
     self.components = _components 
     self.save() 

这应该救你查找现有类型所有的时间。您也可以尝试推迟创建新类型和新组件(使用get()而不是get_or_create()并捕获DoesNotExist异常)并稍后在函数中使用批量插入(这里是doc link