Django 모델 생성 또는 존재하는 경우 업데이트


115

사람의 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

그러나 나는 기존 사람 객체를 어디에서 확인하고 얻을지 모릅니다.

답변:


169

"존재하는 경우 업데이트 다른 생성"사용 사례를 찾고 있다면 @Zags 우수한 답변을 참조하십시오.


장고는 이미 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

나는 1.9 장고 사용하고, 그것은 나에게주고 : AttributeError를 '검색어 세트'개체가 어떤 속성 'update_or_create'가 없다
Ofek 길라

1
이상하다 @OfekGila는 모두 소스 코드문서 확인은 QuerySet있다update_or_create
bakkal

2
제 경우에는 식별자 대신 unique_together를 형성하는 필드 그룹이 있습니다. 이 경우의 사용법은 어떻습니까?
Rakmo

191

귀하의 질문이 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}
)

12
update_or_create해당 사용 사례의 경우 객체를 다시 get_or_create호출 save()하는 것보다 낫기 때문에 +1 합니다.
bakkal

제 경우에는 식별자 대신 unique_together를 형성하는 필드 그룹이 있습니다. 이 경우의 사용법은 어떻습니까?
Rakmo

1
@OmkarDeshpande 식별자는 단지 예일뿐입니다. 다음과 같은 유효한 django 쿼리를 전달할 수 있습니다.Person.objects.get_or_create(a=a, b=b, c=c, defaults={"name": name})
Zags

생성 된 Person에 기본 필드보다 더 많은 필드를 추가하려면 어떻게해야합니까?
Lo Bellin

@LoBellin defaults이 함수에 대한 인수는 모델에 추가 할 필드를 지정하는 곳입니다. 모델의 필드에 지정된 기본값과는 아무 관련이 없습니다
Zags


4

적은 양의 개체에 대해서만 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)

이것은 기껏해야 첫 번째 업데이트 쿼리 만 실행하고 0 행과 일치하는 경우에만 다른 INSERT 쿼리를 실행합니다. 대부분의 행이 실제로 존재한다고 예상하면 성능이 크게 향상됩니다.

그래도 모든 것은 사용 사례에 달려 있습니다. 대부분 삽입을 예상하는 경우 bulk_create () 명령이 옵션이 될 수 있습니다.


3

질문 제목이 질문 본문에 설명 된대로 가져 오거나 생성하는 것이 아니라 생성 또는 업데이트 방법을 묻는 것처럼 보이기 때문에 답변을 추가 할 것이라고 생각했습니다.

객체를 만들거나 업데이트하려는 경우 .save () 메서드는 이미 문서 에서이 동작을 기본적으로 가지고 있습니다 .

Django는 INSERT 또는 UPDATE SQL 문을 사용해야하는 필요성을 추상화합니다. 특히 save ()를 호출하면 Django는 다음 알고리즘을 따릅니다.

객체의 기본 키 속성이 True로 평가되는 값 (즉, None 또는 빈 문자열 이외의 값)으로 설정되면 Django는 UPDATE를 실행합니다. 객체의 기본 키 속성이 설정되지 않았거나 UPDATE가 아무것도 업데이트하지 않은 경우 Django는 INSERT를 실행합니다.

그들이 '업데이트가 아무것도 업데이트하지 않았다면'이라고 말할 때 본질적으로 객체에 부여한 ID가 데이터베이스에 이미 존재하지 않는 경우를 참조한다는 점에 주목할 가치가 있습니다.


1

생성 할 때 입력 중 하나가 기본 키이면 다음으로 충분합니다.

Person.objects.get_or_create(id=1)

동일한 기본 키를 가진 두 데이터가 허용되지 않으므로 자동으로 업데이트됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.