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

时间:2017-01-09 17:19:50

标签: django django-queryset django-orm

目前这个代码似乎在每次循环迭代时都会进入数据库(Postgres)两到四次。首先获取(并创建)Type,然后获取(并创建)Component。有没有办法在更少的数据库旅行中做到这一点?

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" ]
    }
]

1 个答案:

答案 0 :(得分: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()并捕获DoesNotExist异常)并在函数中稍后使用批量插入(这里是doc link