【问题标题】:Correct way to use get_or_create?使用 get_or_create 的正确方法?
【发布时间】:2010-12-28 19:29:49
【问题描述】:

我正在尝试对表单中的某些字段使用 get_or_create,但尝试这样做时出现 500 错误。

其中一行如下所示:

customer.source = Source.objects.get_or_create(name="Website")

上面的代码我得到的错误是:

Cannot assign "(<Source: Website>, False)": "Customer.source" 
   must be a "Source" instance.

【问题讨论】:

    标签: python django


    【解决方案1】:

    来自文档get_or_create

    # get_or_create() a person with similar first names.
    
    p, created = Person.objects.get_or_create(
        first_name='John',
        last_name='Lennon',
        defaults={'birthday': date(1940, 10, 9)},
    )
    
    # get_or_create() didn't have to create an object.
    >>> created
    False
    

    解释: 要评估相似性的字段,必须在defaults 之外提及。其余字段必须包含在defaults 中。如果发生 CREATE 事件,则考虑所有字段。

    看起来你需要返回一个元组,而不是单个变量,这样做:

    customer.source,created = Source.objects.get_or_create(name="Website")
    

    【讨论】:

    • FYI created 是一个布尔值。如果创建则为 True,如果已获取则为 False
    • 额外的save() 是多余的吗?
    • @zypro 就像create(),创建对象并一步保存,不需要任何save()
    • 注意:从 Django 3.2 开始,即使没有创建新对象,也会评估在 defaults 中传递的任何语句。每当create 需要执行复杂的语句时,我最终都会编写try catch 语句。
    【解决方案2】:

    get_or_create 返回一个元组。

    customer.source, created = Source.objects.get_or_create(name="Website")
    

    【讨论】:

    • 或者,如果您不关心布尔标志:customer.source = Source.objects.get_or_create(name="Website")[0]
    • @mipadi 我更喜欢customer.source, _ = Source.objects.get_or_create(name="Website"),因为它使返回元组的事实更加明显,有助于避免将来出现错误。
    【解决方案3】:

    get_or_create() 返回一个元组:

    customer.source, created  = Source.objects.get_or_create(name="Website")
    
    • created 有一个布尔值,是否创建。

    • customer.source 有一个get_or_create()方法的对象。

    【讨论】:

      【解决方案4】:

      在@Tobu 回答和@mipadi 评论之后,以一种更 Python 的方式,如果对创建的标志不感兴趣,我会使用:

      customer.source, _ = Source.objects.get_or_create(name="Website")
      

      【讨论】:

        【解决方案5】:

        您遇到的问题是 get_or_create 的记录功能。

        当使用“defaults”以外的关键字参数时,get_or_create 的返回值是一个实例。这就是为什么它会在返回值中显示括号。

        您可以使用customer.source = Source.objects.get_or_create(name="Website")[0] 来获取正确的值。

        这是文档的链接: http://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create-kwargs

        【讨论】:

          【解决方案6】:

          get_or_create 方法实际上会返回一个元组。

          get_or_create 方法的诀窍在于它实际上返回了一个 (object, created) 的元组。第一个元素是您尝试检索的模型的实例,第二个元素是一个布尔标志,用于判断该实例是否已创建。 True 表示实例是由 get_or_create 方法创建的,False 表示它是从数据库中检索到的

          所以你可以做一些事情来获取源实例

           ```   customer.source = Source.objects.get_or_create(name="Website")[0]
           ```
          

          【讨论】:

            【解决方案7】:

            重要警告。

            在使用 get_or_create https://docs.djangoproject.com/en/4.0/ref/models/querysets/ 之前,您应该注意以下事项。 …… 警告

            假设数据库强制执行关键字参数的唯一性(参见 unique 或 unique_together),此方法是原子的。如果关键字参数中使用的字段没有唯一性约束,则对该方法的并发调用可能会导致插入具有相同参数的多行。

            【讨论】:

              猜你喜欢
              • 2022-01-03
              • 2021-12-08
              • 1970-01-01
              • 2015-12-17
              • 2012-02-23
              • 2013-01-09
              • 2012-04-26
              • 2014-10-24
              相关资源
              最近更新 更多