Coverage for accounts / models.py: 95%

18 statements  

« prev     ^ index     » next       coverage.py v7.13.2, created at 2026-03-10 14:10 +0000

1""" Accounts model (CustomUser records) for storing users customized to allow login by email, etc. 

2 

3Mix in SafeDeleteManager into CustomUserManager for Soft Deletes using safedelete 

4 

5- https://django-safedelete.readthedocs.io/en/latest/managers.html 

6- safe delete of custom users example found at; 

7- https://codeberg.org/mvlaev/Cars/src/branch/main/cars/users_app/models.py" 

8""" 

9from django.contrib.auth.models import AbstractUser, UserManager 

10from common.base_model import BaseModel 

11# from safedelete.models import SafeDeleteModel 

12# from safedelete.models import SOFT_DELETE_CASCADE 

13from safedelete.managers import SafeDeleteManager 

14from auditlog.registry import auditlog 

15 

16 

17# from auditlog.models import AuditlogHistoryField 

18 

19 

20class CustomUserManager(SafeDeleteManager, UserManager): 

21 """Custom User model Manager class ('objects'). 

22 

23 Manager class for CustomUsers (Accounts). Access to this class is through the 'objects' instance attribute of the CustomUser Class. 

24 

25 Soft Delete of Users are implemented through SafeDelete. 

26 See: https://django-safedelete.readthedocs.io/en/latest/managers.html 

27 

28 Args: 

29 param1 (class): SafeDelete manager class mixin 

30 param2 (class): UserManager for CustomUser Abstract Class 

31 

32 """ 

33 

34 def all_deleted(self): 

35 """Returns all soft deleted customuser records. 

36 

37 .. ToDo:: replace accounts.models.CustomUserManager.all_deleted with SafeDeleteManager.deleted_only() 

38 

39 - see: https://django-safedelete.readthedocs.io/en/latest/managers.html 

40 - note: these functions are only found in model manager classes 

41 - thus: all models must declare their custom manager based off of SafeDeleteManager 

42 

43 No arguments are passed to this function when calling it 

44 

45 Returns: 

46 recordset: The soft deleted custom user records. 

47 

48 Example: 

49 

50 .. code-block:: python 

51 

52 # Print out all deleted records 

53 for rec in Account.all_deleted(): 

54 print(rec) 

55 

56 """ 

57 return self.all_with_deleted().filter(deleted__isnull=False) 

58 

59 

60class CustomUser(BaseModel, AbstractUser): 

61 '''CustomUser model - Abstract User customized to allow login by email 

62 

63 Mix in BaseModel to provide: 

64 - soft deletes using django-safedelete 

65 - https://django-safedelete.readthedocs.io/en/latest/index.html 

66 - record history / versioning through django-auditlog 

67 - https://github.com/jazzband/django-auditlog 

68 ''' 

69 objects = CustomUserManager() 

70 

71 def name_or_email(self): 

72 '''Return the user's full name, otherwise return their email.''' 

73 if self.first_name != '' and self.last_name != '': 

74 return "{fname} {lname}".format(fname=self.first_name, lname=self.last_name) 

75 else: 

76 print(f'missing full name, using user email: {self.email}') 

77 return self.email 

78 

79 pass 

80 

81 def __str__(self): 

82 '''What to print when printing a user's record.''' 

83 # fields = [field.name for field in self._meta.fields if field.name != 'password'] 

84 # return ', '.join(f"{field}: {getattr(self, field)}" for field in fields) 

85 return f'{self.email} - {self.last_name}, {self.first_name}' 

86 

87 

88# place as last line in file to ensure it gets all changes into AuditLog 

89auditlog.register(CustomUser, exclude_fields=[ 

90 'password', # protect this field for security reasons 

91 'last_login', # do not update audit log for each login 

92], 

93 )