Foo.objects.get(pk="foo")
<Foo: test>
W bazie danych chcę dodać kolejny obiekt, który jest kopią powyższego obiektu.
Załóżmy, że mój stół ma jeden wiersz. Chcę wstawić obiekt pierwszego wiersza do innego wiersza za pomocą innego klucza podstawowego. Jak mogę to zrobić?
python
django
django-models
użytkownik426795
źródło
źródło
obj.pk
iobj.id
wykonać tę pracę w Django 1.4Dokumentacja Django dla zapytań do bazy danych zawiera sekcję na temat kopiowania instancji modelu . Zakładając, że klucze podstawowe są generowane automatycznie, otrzymujesz obiekt, który chcesz skopiować, ustaw klucz podstawowy
None
i zapisz obiekt ponownie:W tym fragmencie pierwszy
save()
tworzy oryginalny obiekt, a drugisave()
tworzy kopię.Jeśli nadal czytasz dokumentację, istnieją również przykłady obsługi dwóch bardziej złożonych przypadków: (1) kopiowanie obiektu będącego instancją podklasy modelu oraz (2) kopiowanie powiązanych obiektów, w tym obiektów w wielu -wiele relacji.
Uwaga na odpowiedź Miah: Ustawienie pk na
None
jest wspomniane w odpowiedzi Miah, chociaż nie jest przedstawione z przodu i na środku. Więc moja odpowiedź służy głównie podkreśleniu tej metody jako zalecanego przez Django sposobu jej wykonania.Uwaga historyczna: Nie zostało to wyjaśnione w dokumentach Django do wersji 1.4. Było to jednak możliwe przed 1.4.
Możliwa przyszła funkcjonalność: wyżej wymieniona zmiana dokumentacji została wprowadzona w tym bilecie . W wątku komentarza do biletu pojawiła się także dyskusja na temat dodania wbudowanej
copy
funkcji dla klas modeli, ale o ile wiem, zdecydowali się nie rozwiązywać tego problemu. Więc ten „ręczny” sposób kopiowania prawdopodobnie będzie na razie wystarczający.źródło
Uważaj tutaj. Może to być bardzo kosztowne, jeśli jesteś w jakiejś pętli i pobierasz obiekty jeden po drugim. Jeśli nie chcesz wywoływać połączenia z bazą danych, po prostu wykonaj:
Robi to samo, co niektóre z tych innych odpowiedzi, ale nie wywołuje wywołania bazy danych w celu pobrania obiektu. Jest to również przydatne, jeśli chcesz utworzyć kopię obiektu, który nie istnieje jeszcze w bazie danych.
źródło
Użyj poniższego kodu:
źródło
model_to_dict
przyjmujeexclude
parametr, co oznacza, że nie potrzebujesz osobnegopop
:model_to_dict(instance, exclude=['id'])
Jest tu fragment klonu , który możesz dodać do swojego modelu, który to robi:
źródło
if
teraz musi byćif fld.name != old._meta.pk.name
, czyliname
właściwość_meta.pk
instancji.Jak to zrobić, dodano do oficjalnych dokumentów Django w Django 1.4
https://docs.djangoproject.com/en/1.10/topics/db/queries/#copying-model-instances
Oficjalna odpowiedź jest podobna do odpowiedzi Miah, ale dokumenty wskazują na pewne trudności z dziedziczeniem i powiązanymi obiektami, więc prawdopodobnie powinieneś się upewnić, że czytasz dokumenty.
źródło
stable
zamiast numeru wersji w adresie URL, na przykład: docs.djangoproject.com/en/stable/topics/db/queries/…Natknąłem się na kilka błędów z zaakceptowaną odpowiedzią. Oto moje rozwiązanie.
Uwaga: wykorzystuje to rozwiązania, które nie są oficjalnie sankcjonowane w dokumentach Django i mogą przestać działać w przyszłych wersjach. Testowałem to w wersji 1.9.13.
Pierwsze ulepszenie polega na tym, że pozwala ono dalej używać oryginalnej instancji za pomocą
copy.copy
. Nawet jeśli nie zamierzasz ponownie używać instancji, bezpieczniej jest wykonać ten krok, jeśli klonowana instancja została przekazana jako argument funkcji. Jeśli nie, program wywołujący nieoczekiwanie będzie miał inną instancję po powrocie funkcji.copy.copy
wydaje się produkować płytką kopię instancji modelu Django w pożądany sposób. Jest to jedna z rzeczy, których nie udokumentowałem, ale działa ona poprzez trawienie i odprawianie, więc prawdopodobnie jest dobrze obsługiwana.Po drugie, zatwierdzona odpowiedź pozostawi wszelkie wstępnie pobrane wyniki dołączone do nowej instancji. Te wyniki nie powinny być powiązane z nową instancją, chyba że jawnie skopiujesz wiele relacji. Jeśli przejdziesz przez wstępnie pobrane relacje, otrzymasz wyniki, które nie pasują do bazy danych. Złamanie działającego kodu podczas dodawania pobrania wstępnego może być przykrą niespodzianką.
Usuwanie
_prefetched_objects_cache
to szybki i brudny sposób na usunięcie wszystkich prefiksów. Kolejne dostępy działają tak, jakby nigdy nie było pobrania wstępnego. Korzystanie z nieudokumentowanej właściwości, która zaczyna się od znaku podkreślenia, prawdopodobnie powoduje problemy ze zgodnością, ale na razie działa.źródło
_[model_name]_cache
, która po usunięciu mogłem przypisać nowy identyfikator dla tego powiązanego modelu, a następnie wywołaćsave()
. Nadal mogą występować działania niepożądane, których jeszcze nie określiłem.ustawienie pk na None jest lepsze, sinse Django może poprawnie utworzyć pk dla ciebie
źródło
Jest to kolejny sposób klonowania instancji modelu:
źródło
Aby sklonować model z wieloma poziomami dziedziczenia, tj.> = 2 lub ModelC poniżej
Proszę odnieść się do pytania tutaj .
źródło
Spróbuj tego
źródło