2012-10-18 5 views
12

dzięki za poświęcony czas.Django - Sprawdź różnicę pomiędzy starą i nową wartością, gdy przesuwasz metodę zapisu

Jestem na Django 1.4 i mam następujący kod: Jest to zastąpiona metoda zapisu dla mojego modelu Quest.

@commit_on_success 
def save(self, *args, **kwargs): 
    from ib.quest.models.quest_status_update import QuestStatusUpdate 
    created = not self.pk 

    if not created: 
     quest = Quest.objects.get(pk=self) 
     # CHECK FOR SOME OLD VALUE 
    super(Quest, self).save(*args, **kwargs) 

Nie mogłem znaleźć inteligentnego sposobu na zrobienie tego. Wydaje mi się bardzo niemądre, aby utworzyć nowe zapytanie dla obiektu, który obecnie aktualizuję, aby znaleźć starą wartość instancji.

Czy jest lepszy sposób to zrobić?

Dziękuję wszystkim.

Francisco

+0

jaki jest kontekst aktualizacji i zapisania? to znaczy. w widoku bezpośrednio na modelu lub za pomocą ModelForm itp.? – jondykeman

+0

Czy to naprawdę istotne? Używam metody zapisu, aktualizując instancję. Ale tak czy inaczej, to wywołanie jest wykonane z widoku i tam nazwałem 'quest.save()' – Francisco

+0

Nie jestem pewien, czy jest na to czysty sposób. Możesz przekazać stary obiekt do metody 'save()' lub przesłać ją do 'save()' podczas jej wykonywania. – Rohan

Odpowiedz

9

Django nie buforuje starych wartości instancji modelu, więc trzeba to zrobić samemu lub wykonywania innej kwerendy przed zapisaniem.

Jeden wspólny wzór jest użycie wstępnie zapisać sygnał (lub umieścić ten kod bezpośrednio w swojej metody save(), jak zrobiłeś):

old_instance = MyModel.objects.get(pk=instance.pk) 
# compare instance with old_instance, and maybe decide whether to continue 

Jeśli chcesz zachować pamięć podręczną stare wartości, wtedy prawdopodobnie zrobić w kodzie widok:

from copy import deepcopy 
object = MyModel.objects.get(pk=some_value) 
cache = deepcopy(object) 

# Do something with object, and then compare with cache before saving 

było a recent discussion na django-programistów na ten temat, jak również z innych możliwych rozwiązań.

+0

dziękuję za rozwiązanie. To działa, ale w przypadku użycia 'save_as' pk jest ustawione na' None'. Jakiekolwiek obejście tego problemu? –

1

Sprawdzam różnicę do starych wartości za pomocą sygnału odwrócenia django, ale ta sama logika dotyczy sygnałów zapisu. Różnica polega na tym, że chcę zapisać, czy pole zostało zapisane, czy nie.

@receiver(reversion.pre_revision_commit) 
def it_worked(sender, **kwargs): 
    currentVersion = kwargs.pop('versions')[0].field_dict 
    fieldList = currentVersion.keys() 
    fieldList.remove('id') 
    commentDict = {} 
    print fieldList 
    try: 
     pastVersion = reversion.get_for_object(kwargs.pop('instances')[0])[0].field_dict 
    except IndexError: 
     for field in fieldList: 
      commentDict[field] = "Created" 
     comment = commentDict 
    except TypeError: 
     for field in fieldList: 
      commentDict[field] = "Deleted" 
     comment = commentDict 
    else: 
     for field in fieldList: 
      try: 
       pastTest = pastVersion[field] 
      except KeyError: 
       commentDict[field] = "Created" 
      else:  
       if currentVersion[field] != pastTest: 
        commentDict[field] = "Changed" 
       else: 
        commentDict[field] = "Unchanged" 
     comment = commentDict 
    revision = kwargs.pop('revision') 
    revision.comment = comment 
    revision.save() 
    kwargs['revision'] = revision 
    sender.save_revision 
12

można przechowywać starą wartość wewnątrz metody Init:

def __init__(self, *args, **kwargs): 
    super(MyModel, self).__init__(*args, **kwargs) 
    self.old_my_field = self.my_field 

def save(self, *args, **kwargs): 
    print self.old_my_field 
    print self.my_field 

Prawdopodobnie można użyć deepcopy albo coś podobny do skopiowania całego obiektu do późniejszego wykorzystania w zapisywać i usuwać metodami.

+0

Super prosty i łatwy do odczytania. Plus działa idealnie. Doskonałe rozwiązanie. –

Powiązane problemy