创建Django模型或更新(如果存在)

cs7cruho  于 2023-10-21  发布在  Go
关注(0)|答案(9)|浏览(156)

我想创建一个模型对象,比如Person,如果person的id不存在的话,或者我会得到那个person对象。
创建新人员的代码如下:

class Person(models.Model):
    identifier = models.CharField(max_length = 10)
    name = models.CharField(max_length = 20)
    objects = PersonManager()

class PersonManager(models.Manager):
    def create_person(self, identifier):
        person = self.create(identifier = identifier)
        return person

但我不知道在哪里检查和获取现有的person对象。

9lowa7mx

9lowa7mx1#

目前还不清楚你的问题是询问get_or_create方法(至少Django 1.3中可用)还是update_or_create方法(Django 1.7中新增)。这取决于您希望如何更新用户对象。
样品使用如下:

# In both cases, the call will get a person object with matching
# identifier or create one if none exists; if a person is created,
# it will be created with name equal to the value in `name`.

# In this case, if the Person already exists, its existing name is preserved
person, created = Person.objects.get_or_create(
        identifier=identifier, defaults={"name": name}
)

# In this case, if the Person already exists, its name is updated
person, created = Person.objects.update_or_create(
        identifier=identifier, defaults={"name": name}
)
gtlvzcf8

gtlvzcf82#

如果你正在寻找“update if exists else create”用例,请参考@Zags优秀答案
Django已经有一个get_or_create,https://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create
对你来说可能是:

id = 'some identifier'
person, created = Person.objects.get_or_create(identifier=id)

if created:
   # means you have created a new person
else:
   # person just refers to the existing one
bjg7j2ky

bjg7j2ky3#

Django支持这个,检查get_or_create

person, created = Person.objects.get_or_create(name='abc')
if created:
    # A new person object created
else:
    # person object already exists
qyswt5oh

qyswt5oh4#

对于少量的对象,update_or_create可以很好地工作,但是如果你在一个大的集合上工作,它就不能很好地伸缩。update_or_create总是先运行SELECT,然后再运行UPDATE。

for the_bar in bars:
    updated_rows = SomeModel.objects.filter(bar=the_bar).update(foo=100)
        if not updated_rows:
            # if not exists, create new
            SomeModel.objects.create(bar=the_bar, foo=100)

这最多只运行第一个更新查询,并且只有当它匹配零行时才运行另一个更新查询。如果您希望大多数行实际上都存在,这将极大地提高性能。
这一切都取决于你的用例。如果您期望的主要是插入,那么bulk_create()命令可能是一个选项。

dluptydi

dluptydi5#

我想我会添加一个答案,因为你的问题标题看起来像是在问如何创建或更新,而不是像问题正文中描述的那样获取或创建。
如果你确实想创建或更新一个对象,.保存()方法在默认情况下已经有了这个行为,从文档中可以看到:
Django抽象了使用SQL或UPDATE SQL语句的需求。具体来说,当你调用保存()时,Django遵循这个算法:
如果对象的主键属性被设置为一个值,该值的计算结果为True(即,一个值,而不是None或空字符串),Django执行UPDATE。如果对象的主键属性没有设置,或者UPDATE没有更新任何东西,Django会执行一个UPDATE。
值得注意的是,当他们说“如果UPDATE没有更新任何东西”时,他们本质上是指你给对象的id在数据库中不存在的情况。

cgfeq70w

cgfeq70w6#

你也可以像使用get_or_create一样使用update_or_create,这里是我使用update_or_create的模式,假设一个模型Person的id(key),name,age,is_manager作为属性-

update_values = {"is_manager": False}
new_values = {"name": "Bob", "age": 25, "is_manager":True}

obj, created = Person.objects.update_or_create(identifier='id',
                                               defaults=update_values)
if created:
    obj.update(**new_values)
bfrts1fy

bfrts1fy7#

如果创建时的输入之一是主键,这就足够了:

Person.objects.get_or_create(id=1)

如果存在,它将自动更新,因为不允许具有相同主键的两个数据。

1cklez4t

1cklez4t8#

这应该就是你要找的答案

EmployeeInfo.objects.update_or_create(
    #id or any primary key:value to search for
    identifier=your_id, 
    #if found update with the following or save/create if not found
    defaults={'name':'your_name'}
)
bkhjykvo

bkhjykvo9#

出于某种原因,如果对象被更新了(为了在其他系统中传播),我需要有这些信息。我写了一个小小的函数:

# Get object, create it if not existing, update it if existing, and return it with created and updated flag.
# pk must be in kwargs, and if creation needed, all required fields must be in kwargs
def get_or_create_or_update(classmodel, pk, **kwargs) -> (object, bool, bool):
    obj = None
    if pk not in kwargs :
        raise Exception(f"Missing pk '{pk}' in kwargs")
    try:
        obj = classmodel.objects.get(**{pk:kwargs[pk]})
    except classmodel.DoesNotExist:
        # TODO check required fields -> In fact, create will raise an error if required fields are missing
        obj = classmodel.objects.create(**kwargs)
        return obj, True, False
    
    updated = False
    for field in classmodel._meta.get_fields():
        if field.name in kwargs and getattr(obj, field.name) != kwargs[field.name] :
            setattr(obj, field.name, kwargs[field.name])
            updated = True
            
    if updated :
        obj.save()
    return obj, False, updated

相关问题