2017-01-09 2 views
0

В настоящее время этот код, по-видимому, собирается в базу данных (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' и 'component' не выходят из ниоткуда, они извлекаются из базы данных, как вы не можете попасть в базу данных и получить информацию? –

+0

@ShangWang Ну, я полагаю, его можно будет кэшировать локально, но это не вопрос. Цель состоит в том, чтобы уменьшить количество поездок, возможно, до 1 или 2. Я подозреваю, что это было бы возможно, учитывая, что вся информация уже существует во время первой поездки. – dtgq

+1

Почему вы храните массив первичных ключей, а не используете ManyToManyField? –

ответ

1

много времени, 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() и поймайте исключение DoNotExist) и используйте дополнительную вставку позже в функции (здесь doc link)