2013-03-18 8 views
7

Mam model Django o nazwie StaffSettings, który zawiera różne opcje konfiguracji dla użytkowników w mojej aplikacji Django. Każdy użytkownik ma najwyżej jedną pozycję w tabeli StaffSettings.Czy istnieje idiomatyczny sposób na get_or_create, a następnie aktualizację obiektu w Django?

Załóżmy, że jedno ustawienie jest default_year_level i mam kod dla mojego użytkownik obiekty jak:

def set_default_year_level(u, year_level): 
    obj, _created = StaffSettings.objects.get_or_create(user=u) 
    obj.default_year_level = year_level 
    obj.save() 

wolałbym ciało funkcji, aby zmieścić się na jednej linii, ponieważ wydaje się, że przypadku wspólnego użytku, ale jeśli zdefiniowano ją jako

def set_default_year_level(u, year_level): 
    StaffSettings.objects.filter(user=u).update(default_year_level=year_level) 

który działa dobrze, jeśli użytkownik posiada już wiersz w tabeli StaffSettings, ale nie stworzy odpowiedni wiersz, jeśli nie istnieje.

Jaki jest idiomatyczny/najlepszy sposób, aby to zakodować? Czy istnieje jakiś rodzaj funkcji tworzenia dekoratorów/pomocników do obsługi tego idiomu?)

Odpowiedz

5

Nie widzę żadnego problemu z twoją pierwszą funkcją, napisałbym to samo dla tego zastosowania .

Jednak jeśli trzeba tę samą funkcję na wielu polach od modelu i nie chcesz, aby powtórzyć samemu można przekazać boiska w parametrze:

def set_default_value(u, field, value): 
    obj, _created = StaffSettings.objects.get_or_create(user=u) 
    setattr(obj, field, value) 
    obj.save() 

I będę trzymać z dala od update() funkcja i tak jak ta funkcja jest przeznaczona do aktualizacji wielu obiektów na raz i nie wywołać metodę save(), ani sygnałów na swoich modeli (patrz https://docs.djangoproject.com/en/dev/topics/db/queries/#updating-multiple-objects-at-once)

+0

Dziękuję za wzmiankę o niedociągnięciu z aktualizacją(). Chyba przeczytałem to kiedyś, ale zapomniałem. Zrobiłem coś podobnego do tego, co zaproponowałeś, ale zamiast tego ustawiłeś set_default_values ​​(u, ** kwargs), tak, że nie muszę przekazywać ciągu znaków dla pola, i zamiast tego mogę napisać kod taki jak set_default_values ​​(u, default_year_level = year_level) . – bryn

2

Ponieważ Django 1.7 można użyć update_or_create():

def set_default_year_level(u, year_level): 
    obj, _created = StaffSettings.objects.update_or_create(
     user=u, 
     default_year_level=year_level 
    ) 

Albo na bardziej ogólne sprawy, jak wyjaśniono w poprzedniej odpowiedzi:

def set_default_values(u, **kwargs): 
    obj, _created = StaffSettings.objects.update_or_create(user=u, defaults=kwargs) 

który osiąga również swój dodatkowy wymóg

wolałbym ciało funkcji, aby zmieścić na jedna linia

Powiązane problemy