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# Imports 

2 

3from django.conf import settings 

4from django.db import models 

5from django.utils.timezone import now 

6from django.utils.translation import gettext_lazy as _ 

7from superdjango.shortcuts import get_user_name 

8from ..datetime.fields import AutoNowAddDateTimeField, AutoNowDateTimeField 

9from .mixins import AuditMixin 

10 

11# Exports 

12 

13__all__ = ( 

14 "AddedByModel", 

15 "ModifiedByModel", 

16 "ViewedByModel", 

17) 

18 

19# Constants 

20 

21AUTH_USER_MODEL = settings.AUTH_USER_MODEL 

22 

23# Models 

24 

25 

26class AddedByModel(AuditMixin, models.Model): 

27 """Tracks the user that added a record as well as the date and time the record was created. 

28 

29 **Fields** 

30 

31 This class will add the following fields: 

32 

33 - ``added_by`` The user that added the record. 

34 - ``added_dt`` The date and time the record was added. 

35 

36 **Proper Name** 

37 

38 The ``added_by_name`` property is also provided which attempts to return the full name of the user. 

39 

40 **Implementation** 

41 

42 .. code-block:: py 

43 

44 class Project(AddedByModel): 

45 

46 # ... 

47 

48 class Meta: 

49 get_latest_by = "added_dt" 

50 ordering = ["-added_dt"] 

51 

52 """ 

53 

54 # blank must be True to allow form submission. 

55 added_by = models.ForeignKey( 

56 AUTH_USER_MODEL, 

57 blank=True, 

58 on_delete=models.PROTECT, 

59 related_name="%(app_label)s_%(class)s_added_records", 

60 verbose_name=_("added by") 

61 ) 

62 

63 added_dt = AutoNowAddDateTimeField( 

64 _("added date/time"), 

65 help_text=_("Date and time the record was created.") 

66 ) 

67 

68 class Meta: 

69 abstract = True 

70 

71 def audit(self, user, commit=True): 

72 """Check for ``added_by_id`` just in case the primary key is being managed at run time. 

73 

74 A ``RelatedObjectDoesNotExist`` error will be thrown if we just look for ``added_by``, so the simplest thing to 

75 do appears to be checking for the primary key instead. 

76 

77 """ 

78 # noinspection PyUnresolvedReferences 

79 if not self.pk or not self.added_by_id: 

80 self.added_by = user 

81 

82 super().audit(user, commit=commit) 

83 

84 @property 

85 def added_by_name(self): 

86 """Get the full name or user name of the user that added the record. 

87 

88 :rtype: str 

89 

90 """ 

91 return get_user_name(self.added_by) 

92 

93 

94class ModifiedByModel(AuditMixin): 

95 """Tracks the user that last updated a record as well as the date and time of the last update. 

96 

97 **Fields** 

98 

99 This class will add the following fields: 

100 

101 - ``modified_by`` The user that modified record. 

102 - ``modified_dt`` The date and time the modified was added. 

103 

104 **Proper Name** 

105 

106 The ``modified_by_name`` property is also provided which attempts to return the full name of the user. 

107 

108 **Implementation** 

109 

110 .. code-block:: py 

111 

112 class MyModel(ModifiedByModel): 

113 

114 # ... 

115 

116 class Meta: 

117 ordering = ["modified_dt"] 

118 

119 """ 

120 

121 # blank must be True to allow form submission 

122 modified_by = models.ForeignKey( 

123 AUTH_USER_MODEL, 

124 blank=True, 

125 on_delete=models.PROTECT, 

126 related_name="%(app_label)s_%(class)s_modified_records", 

127 verbose_name=_("modified by") 

128 ) 

129 

130 modified_dt = AutoNowDateTimeField( 

131 _("modified date/time"), 

132 help_text=_("Date and time the record was last modified.") 

133 ) 

134 

135 class Meta: 

136 abstract = True 

137 

138 def audit(self, user, commit=True): 

139 """Always sets ``modified_by`` to the given user.""" 

140 self.modified_by = user 

141 

142 super().audit(user, commit=commit) 

143 

144 @property 

145 def modified_by_name(self): 

146 """Get the full name or user name of the user that last modified the record. 

147 

148 :rtype: str 

149 

150 """ 

151 return get_user_name(self.modified_by) 

152 

153 

154class ViewedByModel(AuditMixin): 

155 """Tracks the user that view a record as well as the date and time the record was last viewed. 

156 

157 **Fields** 

158 

159 This class will add the following fields: 

160 

161 - ``viewed_by`` The user that viewed record. 

162 - ``viewed_dt`` The date and time the record was last viewed. 

163 

164 **Proper Name** 

165 

166 The ``viewed_by_name`` property is also provided which attempts to return the full name of the user. 

167 

168 **Implementation** 

169 

170 .. code-block:: python 

171 

172 class MedicalRecord(ViewedByModel): 

173 # ... 

174 

175 """ 

176 

177 viewed_by = models.ForeignKey( 

178 AUTH_USER_MODEL, 

179 blank=True, 

180 null=True, 

181 on_delete=models.SET_NULL, 

182 related_name="%(app_label)s_%(class)s_viewed_records", 

183 verbose_name=_("viewed by") 

184 ) 

185 

186 viewed_dt = models.DateTimeField( 

187 _("viewed date/time"), 

188 blank=True, 

189 help_text=_("Date and time the record was last viewed."), 

190 null=True 

191 ) 

192 

193 class Meta: 

194 abstract = True 

195 

196 def audit(self, user, commit=True): 

197 """Update viewed fields. 

198 

199 .. important:: 

200 This method makes calls to ``super()`` which may also trigger the update of other fields if the model also 

201 extends :py:class:`AddedByModel` or :py:class:`ModifiedByModel`. See ``mark_viewed()`` if you just want to 

202 update the ``viewed_by`` and ``viewed_dt`` fields. 

203 

204 """ 

205 self.viewed_by = user 

206 self.viewed_dt = now() 

207 

208 super().audit(user, commit=commit) 

209 

210 def mark_viewed(self, user, commit=True): 

211 """Mark the record as viewed. 

212 

213 :param user: The user that reviewed the record. 

214 :type user: AUTH_USER_MODEL 

215 

216 :param commit: Indicates the record should be saved after updating the field. 

217 :type commit: bool 

218 

219 """ 

220 self.viewed_by = user 

221 self.viewed_dt = now() 

222 

223 if commit: 

224 self.save(update_fields=["viewed_by", "viewed_dt"]) 

225 

226 def mark_unviewed(self, commit=True): 

227 """Mark the record as "un-viewed", removing the last viewed data. 

228 

229 :param commit: Indicates the record should be saved after updating the field. 

230 :type commit: bool 

231 

232 """ 

233 self.viewed_by = None 

234 self.viewed_dt = None 

235 

236 if commit: 

237 self.save(update_fields=["viewed_by", "viewed_dt"]) 

238 

239 @property 

240 def viewed_by_name(self): 

241 """Get the full name or user name of the user that last viewed the record. 

242 

243 :rtype: str 

244 

245 """ 

246 return get_user_name(self.viewed_by)