Utwórz, jeśli nie istnieje


81

Mam aplikację Django, która odczytuje dane z internetowego interfejsu API i umieszcza je w bazie danych.
Czy istnieje sposób na utworzenie nowego obiektu z trybu, ale zapobieganie zduplikowaniu wyjątku, jeśli obiekt już istnieje?

Innymi słowy, czy istnieje sposób na zapisanie obiektu, ale nie robienie niczego, jeśli już istnieje?

Odpowiedzi:


161

9
uczynienie go linkiem do dokumentów dodaje kilka znaków (i wydaje mi się, że jest to lepsza odpowiedź)
drugi

4
To wydaje się powodować 2 zapytania. Jeśli chcę tylko zapisać obiekt na wypadek, gdyby nie istniał, czy jest sposób z tylko jednym zapytaniem? Myślę, że przechwytywanie IntegrityErrorpowoduje przerwanie bieżącej transakcji i nie jest wystarczające.
Amir Ali Akbari

można złapać błąd integralności jeśli dodać punkt zapisu, na przykład za pomocą transaction.atomic(upewnij się złapać poza ten atomicblok, tzn try: with acomic: create; except IntegrityErrorJest to także trudne, aby upewnić się, że nie złapać. inne błędy integralności niż ta, którą zamierzasz
drugi

Jeśli jesteś w stanie złapać IntegrityError, moje testy pokazują, że skraca czas wykonywania prawie o połowę, gdy rekord istnieje w porównaniu z get_or_create().
Ron


3

Wygląda na to, że w nowszych wersjach Django funkcja save () domyślnie wykonuje UPDATE lub INSERT. Zobacz tutaj .


wygląda na to, że powinien automatycznie wybierać dobrze, jednak w mojej bazie danych obecnie kopiuje wpisy za każdym razem, gdy uruchamiam skrypt, aby zapełnić bazę danych.
martin-martin

metoda save () sprawdza, czy PK modelu ma wartość. Autor musiałby wysłać zapytanie do bazy danych, aby uzyskać instancję modelu z poprawną PK, aby użyć tej techniki. Samo użycie save () nie robi magii.
chickahoona

0

Można to osiągnąć za pomocą Model.objects.get_or_create()

Przykład

obj, created = Person.objects.get_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'birthday': date(1940, 10, 9)},
)

Wszelkie argumenty słów kluczowych (tutaj first_name i last_name ) przekazane do get_or_create () - z wyjątkiem opcjonalnego o nazwie defaults - zostaną użyte do zapytania w bazie danych (znalezienia obiektu) w bazie danych.

Zwraca krotkę, jeśli obiekt zostanie znaleziony, get_or_create () zwraca krotkę tego obiektu i False.

Uwaga : to samo można osiągnąć za pomocą try exceptinstrukcji
Przykład:

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()
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.