Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# Exports 

2 

3__all__ = ( 

4 "get_field_changes", 

5 "FieldChange", 

6) 

7 

8# Functions 

9 

10 

11def get_field_changes(form, model, record=None): 

12 """Get the changed fields for a given form and record. 

13 

14 :param form: The validated form instance. 

15 

16 :param model: The model class represented by the record. 

17 

18 :param record: The current record instance. It is safe to pass ``None``. 

19 

20 :rtype: list[superdjango.db.history.utils.FieldChange] 

21 :returns: A list pf changed fields when record is not ``None``. Otherwise, an empty list. 

22 

23 """ 

24 # It's possible at runtime that a form instance is None. If so, there's nothing to compare and we don't want to 

25 # raise an error because we will assume it's intentional. 

26 if form is None: 

27 return list() 

28 

29 # We might not have received a record, for example if this is a create operation. So again, don't raise an error. 

30 if record is None: 

31 return list() 

32 

33 # Get the existing data. 

34 old_record = model.objects.get(pk=record.pk) 

35 

36 # Compare old data with submitted data. 

37 changes = list() 

38 # noinspection PyProtectedMember 

39 for field in model._meta.get_fields(): 

40 if field.name in form.cleaned_data: 

41 old_value = getattr(old_record, field.name) 

42 if old_value != form.cleaned_data[field.name]: 

43 change = FieldChange(field.name, form.cleaned_data[field.name], old_value, label=field.verbose_name) 

44 changes.append(change) 

45 

46 # Return the change instances. 

47 return changes 

48 

49# Classes 

50 

51 

52class FieldChange(object): 

53 """Wraps the change that has occurred to a given field.""" 

54 

55 def __init__(self, field_name, new_value, old_value, label=None): 

56 """Initialize a field change. 

57 

58 :param field_name: The name of the field that was changed. 

59 :type field_name: str 

60 

61 :param new_value: The new value, e.g. from the cleaned data of a form. 

62 

63 :param old_value: The existing value from the database prior to save. 

64 

65 :param label: The field label (verbose name). 

66 :type label: str 

67 

68 """ 

69 self.field_label = label or field_name.replace("_", " ") 

70 self.field_name = field_name 

71 self.new_value = new_value 

72 self.old_value = old_value 

73 

74 def __repr__(self): 

75 return "<%s %s: %s -> %s>" % (self.__class__.__name__, self.field_name, self.old_value, self.new_value) 

76 

77 def __str__(self): 

78 return "%s: %s -> %s" % (self.field_label, self.old_value, self.new_value)