zoukankan      html  css  js  c++  java
  • get_or_create函数

    get_or_create(defaults=None, **kwargs)

    一个通过给出的kwargs 来查询对象的便捷方法(如果你的模型中的所有字段都有默认值,可以为空),需要的话创建一个对象。

    返回一个由(object, created)组成的元组,元组中的object 是一个查询到的或者是被创建的对象, created 是一个表示是否创建了新的对象的布尔值。

    这主要用作样板代码的一种快捷方式。例如:

    try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
    except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()
    如果模型的字段数量较大的话,这种模式就变的非常不易用了。
    上面的示例可以用get_or_create()重写 :

    obj, created = Person.objects.get_or_create(first_name='John', last_name='Lennon',
    defaults={'birthday': date(1940, 10, 9)})
    
    
    任何传递给 get_or_create() 的关键字参数,除了一个可选的defaults,都将传递给get() 调用。
    如果查找到一个对象,get_or_create() 返回一个包含匹配到的对象以及False 组成的元组。
    如果查找到的对象超过一个以上,get_or_create 将引发MultipleObjectsReturned。
    如果查找不到对象, get_or_create() 将会实例化并保存一个新的对象,
    返回一个由新的对象以及True 组成的元组。新的对象将会大概按照以下的逻辑创建:

    params = {k: v for k, v in kwargs.items() if '__' not in k}
    params.update(defaults)
    obj = self.model(**params)
    
    
    它表示从非’defaults’ 且不包含双下划线的关键字参数开始(暗示这是一个不精确的查询)。
    然后将defaults 的内容添加进来,覆盖必要的键,并使用结果作为关键字参数传递给模型类。
    这是对用到的算法的简单描述,但它包含了所有的相关的细节。
    内部的实现有更多的错误检查并处理一些边缘条件;如果感兴趣,请阅读代码。

    如果你有一个名为defaults的字段,并且想在get_or_create() 是用它作为精确查询,只需要使用’defaults__exact’,像这样:

    Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'})
    
    

    当你使用手动指定的主键时,get_or_create() 方法与create()方法有相似的错误行为 。如果需要创建一个对象而该对象的主键早已存在于数据库中,IntegrityError 异常将会被触发。

    这个方法假设正确使用原子操作,正确的数据库配置和底层数据库的正确行为。然而,如果数据库级别没有对get_or_create 中用到的kwargs 强制要求唯一性(参见unique 和 unique_together),这个方法容易导致竞态条件可能会仍具有相同参数的多行同时插入。

    如果你正在使用MySQL,请确保使用READ COMMITTED 隔离级别而不是默认的REPEATABLE READ,否则你将会遇到get_or_create 引发IntegrityError 但对象在接下来的get() 调用中并不存在的情况。

    最后讲一句get_or_create() 在Django 视图中的使用。请确保只在POST 请求中使用,除非你有充分的理由。GET 请求不应该对数据有任何影响。而POST 则用于对数据产生影响的请求。更多信息,参见HTTP 细则中的安全的方法。

    警告

    你可以通过ManyToManyField 属性和反向关联使用get_or_create()。在这种情况下,你应该限制查询在关联的上下文内部。如果你不一致地使用它,将可能导致完整性问题。

    根据下面的模型:

    class Chapter(models.Model):
    title = models.CharField(max_length=255, unique=True)
    class Book(models.Model):
    title = models.CharField(max_length=256)
    chapters = models.ManyToManyField(Chapter)
    你可以通过Book 的chapters 字段使用get_or_create(),但是它只会获取该Book 内部的上下文:
    >>> book = Book.objects.create(title="Ulysses")
    >>> book.chapters.get_or_create(title="Telemachus")
    (<Chapter: Telemachus>, True)
    >>> book.chapters.get_or_create(title="Telemachus")
    (<Chapter: Telemachus>, False)
    >>> Chapter.objects.create(title="Chapter 1")
    <Chapter: Chapter 1>
    >>> book.chapters.get_or_create(title="Chapter 1")
    # Raises IntegrityError
    发生这个错误时因为它尝试通过Book “Ulysses” 获取或者创建“Chapter 1”,
    但是它不能:关联关系不能获取这个chapter 因为它与这个book 不关联,
    但因为title 字段是唯一的它仍然不能创建。


    本文出自:https://zhuanlan.zhihu.com/p/34856119


  • 相关阅读:
    Web全栈探索,Vue基础系列,前后端交互(三)
    Web全栈探索,Vue基础系列,前后端交互(二)
    Web全栈探索,Vue基础系列,前后端交互(一)
    Web全栈探索,Vue基础系列,常用特性(六)Vue的生命周期
    Web全栈探索,Vue基础系列,常用特性(五)过滤器
    Web全栈探索,Vue基础系列,常用特性(四)侦听器
    Web全栈探索,Vue基础系列,常用特性(三)计算属性
    Web全栈探索,Vue基础系列,常用特性(二)自定义指令
    Web全栈探索,Vue基础系列,常用特性(一)表单的使用
    Web全栈探索,Vue基础系列,模板语法(三)
  • 原文地址:https://www.cnblogs.com/zhongbokun/p/9732698.html
Copyright © 2011-2022 走看看