Coverage for family/admin_views.py: 100%

41 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-07-05 19:26 +0800

1""" 

2Custom admin views and context processors for Family Knowledge Management System 

3""" 

4 

5from django.contrib import admin 

6from django.db.models import Count 

7from django.utils import timezone 

8from datetime import timedelta 

9from .models import Person, Story, Event, Multimedia, Timeline 

10 

11 

12def get_family_dashboard_context(): 

13 """ 

14 Generate context data for the family dashboard 

15 """ 

16 try: 

17 # Family statistics 

18 family_stats = { 

19 'person_count': Person.objects.count(), 

20 'story_count': Story.objects.count(), 

21 'event_count': Event.objects.count(), 

22 'multimedia_count': Multimedia.objects.count(), 

23 } 

24 

25 # Recent activities (last 30 days) 

26 thirty_days_ago = timezone.now() - timedelta(days=30) 

27 

28 recent_activities = [] 

29 

30 # Recent stories 

31 recent_stories = Story.objects.filter( 

32 created_at__gte=thirty_days_ago 

33 ).order_by('-created_at')[:3] 

34 

35 for story in recent_stories: 

36 recent_activities.append({ 

37 'icon': '📖', 

38 'title': f'新故事: {story.title[:30]}...' if len(story.title) > 30 else f'新故事: {story.title}', 

39 'time': story.created_at.strftime('%m月%d日'), 

40 'url': f'/admin/family/story/{story.id}/change/', 

41 }) 

42 

43 # Recent people 

44 recent_people = Person.objects.filter( 

45 created_at__gte=thirty_days_ago 

46 ).order_by('-created_at')[:2] 

47 

48 for person in recent_people: 

49 recent_activities.append({ 

50 'icon': '👥', 

51 'title': f'新成员: {person.name}', 

52 'time': person.created_at.strftime('%m月%d日'), 

53 'url': f'/admin/family/person/{person.id}/change/', 

54 }) 

55 

56 # Recent multimedia 

57 recent_media = Multimedia.objects.filter( 

58 uploaded_at__gte=thirty_days_ago 

59 ).order_by('-uploaded_at')[:2] 

60 

61 for media in recent_media: 

62 recent_activities.append({ 

63 'icon': '📸', 

64 'title': f'新照片: {media.title or "未命名"}', 

65 'time': media.uploaded_at.strftime('%m月%d日'), 

66 'url': f'/admin/family/multimedia/{media.id}/change/', 

67 }) 

68 

69 # Sort by time (most recent first) 

70 recent_activities.sort(key=lambda x: x['time'], reverse=True) 

71 recent_activities = recent_activities[:5] # Limit to 5 items 

72 

73 # Upcoming events (next 60 days) 

74 upcoming_date = timezone.now() + timedelta(days=60) 

75 upcoming_events = Event.objects.filter( 

76 date__gte=timezone.now().date(), 

77 date__lte=upcoming_date.date() 

78 ).order_by('date')[:5] 

79 

80 return { 

81 'family_stats': family_stats, 

82 'recent_activities': recent_activities, 

83 'upcoming_events': upcoming_events, 

84 } 

85 

86 except Exception as e: 

87 # Fallback in case of any errors 

88 return { 

89 'family_stats': { 

90 'person_count': 0, 

91 'story_count': 0, 

92 'event_count': 0, 

93 'multimedia_count': 0, 

94 }, 

95 'recent_activities': [], 

96 'upcoming_events': [], 

97 } 

98 

99 

100class FamilyAdminSite(admin.AdminSite): 

101 """ 

102 Custom admin site with family-specific customizations 

103 """ 

104 site_header = '家族知识管理系统' 

105 site_title = '家族知识管理' 

106 index_title = '欢迎来到家族知识管理系统' 

107 

108 def index(self, request, extra_context=None): 

109 """ 

110 Override the admin index to include family dashboard data 

111 """ 

112 if extra_context is None: 

113 extra_context = {} 

114 

115 # Add family dashboard context 

116 dashboard_context = get_family_dashboard_context() 

117 extra_context.update(dashboard_context) 

118 

119 return super().index(request, extra_context) 

120 

121 

122# Create custom admin site instance 

123family_admin_site = FamilyAdminSite(name='family_admin') 

124 

125 

126def family_dashboard_context_processor(request): 

127 """ 

128 Context processor to provide family dashboard data to templates 

129 """ 

130 if request.path.startswith('/admin/'): 

131 return get_family_dashboard_context() 

132 return {}