Zapytania Django - ID kontra PK

203

Podczas pisania zapytań django można użyć zarówno id / pk jako parametrów zapytania.

Object.objects.get(id=1)
Object.objects.get(pk=1)

Wiem, że pk oznacza Primary Key i jest tylko skrótem, zgodnie z dokumentacją django. Jednak nie jest jasne, kiedy należy używać id lub pk.

Sztuka
źródło
Oto odpowiednie doktryny: zaid i zapk
Lutz Prechelt
Chcesz wiedzieć, czy coś więcej to docs.djangoproject.com/en/1.11/topics/db/queries/…
Rajan Chauhan
Sprawdź Zaktualizowana wersja tutaj docs.djangoproject.com/en/2.2/topics/db/models/…
Tessaracter

Odpowiedzi:

224

To nie ma znaczenia pkjest bardziej niezależny od rzeczywistego pola klucza pierwotnego czyli nie trzeba dbać, czy pole klucz podstawowy jest nazywany idlub object_idczy cokolwiek innego.

Zapewnia również większą spójność, jeśli masz modele z różnymi polami klucza podstawowego.

Felix Kling
źródło
34
Tak. Po prostu użyj pk. Zawsze.
cethegeek
47
idjest również wbudowaną funkcją Pythona, dlatego wolę używać pk z tego powodu.
Thierry Lam
5
Tak, pklepiej. Zobacz dokumentację wbudowanej funkcjiid w standardowej bibliotece Python. (Tak samo jest w Pythonie 2 ).
Lutz Prechelt
26

W projektach Django, o których wiem, że pkzawsze zwraca id, wolę używać, idgdy nie koliduje z id()funkcją (wszędzie oprócz nazw zmiennych). Wynika to z tego, że pkjest to właściwość 7 razy wolniejsza niż idczasochłonne wyszukiwanie pknazwy atrybutu meta.

%timeit obj.id
46 ns ± 0.187 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit obj.pk
347 ns ± 11.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Oto odpowiedni kod Django:

def _get_pk_val(self, meta=None):
    meta = meta or self._meta
    return getattr(self, meta.pk.attname)

def _set_pk_val(self, value):
    return setattr(self, self._meta.pk.attname, value)

pk = property(_get_pk_val, _set_pk_val)

To naprawdę rzadki przypadek, kiedy muszę użyć zmiennej o nazwie pk. Wolę używać czegoś bardziej szczegółowego, jak user_idzamiast pk.

Przestrzeganie tej samej konwencji jest preferowane w całym projekcie. W twoim przypadku idjest to nazwa parametru, a nie właściwość, więc prawie nie ma różnicy w taktowaniu. Nazwy parametrów nie kolidują z nazwą wbudowanej id()funkcji, więc można z niej bezpiecznie korzystać id.

Podsumowując, od Ciebie zależy, czy chcesz użyć nazwy pola, idczy pkskrótu. Jeśli nie tworzysz biblioteki dla Django i używasz automatycznych pól klucza podstawowego dla wszystkich modeli, możesz bezpiecznie używać idwszędzie, co czasami jest szybsze. Z drugiej strony, jeśli chcesz mieć uniwersalny dostęp do (prawdopodobnie niestandardowych) pól klucza głównego, używaj go pkwszędzie. Jedna trzecia mikrosekundy to nic dla sieci.

utapyngo
źródło