为什么`get_or_create`在找到对象时从默认值执行表达式?

时间:2016-09-28 17:10:34

标签: django

lang_group = 'en'
for place_category in place['categories']:
        translation, created = \
            PlaceTypesTranslations.objects.get_or_create(
                name=place_category, lang_group=lang_group,
                    defaults={'place_type_group': PlaceTypesGroups.objects.create()})

在这种情况下,如果循环有1000次迭代,例如,500次created=True和其他500次created=False,则无论如何都将创建1000 PlaceTypesGroups,因此出于某种原因甚至如果get_or_create返回get,则无论如何都会执行defaults

相同的算法,但方法不同:

lang_group = 'en'
for place_category in place['categories']:
    if PlaceTypesTranslations.objects.filter(name=place_category, lang_group=lang_group).exists():
        place_cat_trans = PlaceTypesTranslations.objects.get(name=place_category, lang_group=lang_group)
        place_group = place_cat_trans.place_type_group
    else:
        place_group = PlaceTypesGroups.objects.create()
        place_cat_trans = PlaceTypesTranslations.objects.create(name=place_category,
                                                                lang_group=lang_group,
                                                                place_type_group=place_group)

在这种情况下,只会按预期创建500次PlaceTypesGroups。 这是为什么?我在第一种情况下没有看到什么?为什么get_or_create会创建1000 PlaceTypesGroups

2 个答案:

答案 0 :(得分:2)

这就是Python表达式始终有效的方式。在将表达式本身传递给函数或方法之前,必须始终完全评估表达式中的任何内容。

但是,Django特别允许您在defaults哈希中传递可调用而不是值。所以你可以这样做:

      PlaceTypesTranslations.objects.get_or_create(
            name=place_category, lang_group=lang_group,
                defaults={'place_type_group': PlaceTypesGroups.objects.create})

它将根据需要调用create方法。

答案 1 :(得分:0)

它被称为1000x,因为您正在从函数中分配返回的值。我将从一个简单的例子开始:

place_type_group = some_function()

变量现在包含函数返回的任何内容,对吧?

现在,如果你将它包装成字典,它仍然是一样的东西,只需将它包装到字典中:

dict(place_type_group = some_function())

dict中的元素仍然包含从some_function()

返回的值

上面的字典对于下面的代码是相同的,这是你在代码中所做的(即将函数返回值赋值给变量)

{'place_type_group': some_function() }