Coverage for src / ptf_tools / admin.py: 72%

79 statements  

« prev     ^ index     » next       coverage.py v7.13.2, created at 2026-08-19 12:55 +0000

1from django import forms 

2from django.contrib import admin 

3from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin 

4from django.contrib.auth.admin import UserAdmin as BaseUserAdmin 

5from django.contrib.auth.models import Group, User 

6from django.db.models import QuerySet 

7from django.http import HttpRequest 

8from mersenne_cms.admin import PageAdmin, Site 

9from mersenne_cms.models import Page 

10from ptf.admin import ptf_admin 

11 

12from comments_moderation.forms import UserCommentModeratorForm 

13from comments_moderation.models import CommentModerator 

14from ptf_tools.models import CollectionGroup 

15 

16from .forms import InvitationAdminAddForm, InvitationAdminChangeForm 

17from .models import ( 

18 EditorialToolsChoices, 

19 FieldsToUpdateChoices, 

20 Invitation, 

21 UserRole, 

22) 

23 

24 

25class GroupInline(admin.StackedInline): 

26 model = CollectionGroup 

27 can_delete = False 

28 verbose_name_plural = "collection groups" 

29 

30 

31class GroupAdmin(BaseGroupAdmin): 

32 inlines = (GroupInline,) 

33 list_display = ("name", "get_collections") 

34 

35 def get_queryset(self, request: HttpRequest) -> QuerySet: 

36 return ( 

37 super() 

38 .get_queryset(request) 

39 .prefetch_related("collectiongroup", "collectiongroup__collections") 

40 ) 

41 

42 @admin.display(description="Collections") 

43 def get_collections(self, obj) -> str: 

44 return obj.collectiongroup.get_collections() 

45 

46 

47# Re-register GroupAdmin 

48ptf_admin.unregister(Group) 

49ptf_admin.register(Group, GroupAdmin) 

50ptf_admin.register(Page, PageAdmin) 

51ptf_admin.register(Site) 

52 

53 

54class ModeratorUserInline(admin.StackedInline): 

55 model = CommentModerator 

56 can_delete = False 

57 fields = ("is_moderator", "collections") 

58 form = UserCommentModeratorForm 

59 add_form = UserCommentModeratorForm 

60 

61 

62class UserAdmin(BaseUserAdmin): 

63 inlines = (ModeratorUserInline,) 

64 list_display = ( 

65 "username", 

66 "email", 

67 "first_name", 

68 "last_name", 

69 "is_staff", 

70 "is_superuser", 

71 "is_moderator", 

72 ) 

73 

74 def get_queryset(self, request: HttpRequest) -> QuerySet: 

75 return super().get_queryset(request).prefetch_related("comment_moderator") 

76 

77 @admin.display( 

78 description="Moderator", 

79 ordering="comment_moderator__is_moderator", 

80 ) 

81 @admin.display(boolean=True) 

82 def is_moderator(self, obj) -> bool: 

83 return hasattr(obj, "comment_moderator") and obj.comment_moderator.is_moderator 

84 

85 

86ptf_admin.unregister(User) 

87ptf_admin.register(User, UserAdmin) 

88 

89 

90class InvitationAdmin(admin.ModelAdmin): 

91 list_display = ("email", "first_name", "last_name", "sent", "accepted", "key") 

92 raw_id_fields = ("inviter",) 

93 

94 readonly_fields = ["accepted", "key", "sent", "inviter", "created"] 

95 

96 def get_form(self, request, obj=None, **kwargs): 

97 if obj: 

98 kwargs["form"] = InvitationAdminChangeForm 

99 else: 

100 kwargs["form"] = InvitationAdminAddForm 

101 kwargs["form"].user = request.user 

102 kwargs["form"].request = request 

103 return super().get_form(request, obj, **kwargs) 

104 

105 def get_readonly_fields(self, request: HttpRequest, obj): 

106 """ 

107 Disable editing the email field once the invite has already been sent. 

108 """ 

109 readonly_fields = list(self.readonly_fields) 

110 if obj: 

111 readonly_fields += ["email"] 

112 return readonly_fields 

113 

114 

115ptf_admin.register(Invitation, InvitationAdmin) 

116 

117 

118class UserRoleForm(forms.ModelForm): 

119 fields_to_update = forms.MultipleChoiceField( 

120 choices=FieldsToUpdateChoices.choices, widget=forms.CheckboxSelectMultiple, required=False 

121 ) 

122 editorial_tools = forms.MultipleChoiceField( 

123 choices=EditorialToolsChoices.choices, widget=forms.CheckboxSelectMultiple, required=False 

124 ) 

125 

126 class Meta: 

127 model = UserRole 

128 fields = "__all__" 

129 

130 

131class UserRoleAdmin(admin.ModelAdmin): 

132 form = UserRoleForm 

133 

134 def formfield_for_manytomany(self, db_field, request, **kwargs): 

135 if db_field.name == "users": 

136 kwargs["queryset"] = User.objects.all() 

137 self.filter_horizontal = ("users",) 

138 return super().formfield_for_manytomany(db_field, request, **kwargs) 

139 

140 

141ptf_admin.register(UserRole, UserRoleAdmin)