• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rdmorganiser / rdmo / 14404330126

11 Apr 2025 01:31PM UTC coverage: 90.789% (+0.3%) from 90.478%
14404330126

push

github

web-flow
Merge pull request #1195 from rdmorganiser/2.3.0

RDMO 2.3.0 ⭐

989 of 1076 branches covered (91.91%)

9176 of 10107 relevant lines covered (90.79%)

3.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.85
rdmo/projects/admin.py
1
from django import forms
4✔
2
from django.contrib import admin
4✔
3
from django.db.models import Prefetch
4✔
4
from django.urls import reverse
4✔
5
from django.utils.safestring import mark_safe
4✔
6
from django.utils.translation import gettext_lazy as _
4✔
7

8
from .models import (
4✔
9
    Continuation,
10
    Integration,
11
    IntegrationOption,
12
    Invite,
13
    Issue,
14
    IssueResource,
15
    Membership,
16
    Project,
17
    Snapshot,
18
    Value,
19
    Visibility,
20
)
21
from .validators import ProjectParentValidator
4✔
22

23

24
class ProjectAdminForm(forms.ModelForm):
4✔
25

26
    class Meta:
4✔
27
        model = Project
4✔
28
        fields = [
4✔
29
            'parent',
30
            'site',
31
            'title',
32
            'description',
33
            'catalog',
34
            'views'
35
        ]
36

37

38
    def clean(self):
4✔
39
        super().clean()
×
40
        ProjectParentValidator(self.instance)(self.cleaned_data)
×
41

42

43
@admin.register(Project)
4✔
44
class ProjectAdmin(admin.ModelAdmin):
4✔
45
    form = ProjectAdminForm
4✔
46

47
    search_fields = ('title', 'user__username')
4✔
48
    list_display = ('title', 'owners', 'updated', 'created')
4✔
49
    readonly_fields = ('progress_count', 'progress_total')
4✔
50

51
    def get_queryset(self, request):
4✔
52
        return Project.objects.prefetch_related(
×
53
            Prefetch(
54
                'memberships',
55
                queryset=Membership.objects.filter(role='owner').select_related('user'),
56
                to_attr='owner_memberships'
57
            )
58
        )
59

60
    def owners(self, obj):
4✔
61
        return [membership.user.get_full_name() for membership in obj.owner_memberships]
×
62

63

64
@admin.register(Membership)
4✔
65
class MembershipAdmin(admin.ModelAdmin):
4✔
66
    search_fields = ('project__title', 'user__username', 'role')
4✔
67
    list_display = ('project', 'user', 'role')
4✔
68

69

70
@admin.register(Continuation)
4✔
71
class ContinuationAdmin(admin.ModelAdmin):
4✔
72
    search_fields = ('project__title', 'user__username')
4✔
73
    list_display = ('project', 'user', 'page')
4✔
74

75

76
@admin.register(Visibility)
4✔
77
class VisibilityAdmin(admin.ModelAdmin):
4✔
78
    search_fields = ('project__title', 'sites', 'groups')
4✔
79
    list_display = ('project', 'sites_list_display', 'groups_list_display')
4✔
80
    filter_horizontal = ('sites', 'groups')
4✔
81

82
    @admin.display(description=_('Sites'))
4✔
83
    def sites_list_display(self, obj):
4✔
84
        return _('all Sites') if obj.sites.count() == 0 else ', '.join([
×
85
            site.domain for site in obj.sites.all()
86
        ])
87

88
    @admin.display(description=_('Groups'))
4✔
89
    def groups_list_display(self, obj):
4✔
90
        return _('all Groups') if obj.groups.count() == 0 else ', '.join([
×
91
            group.name for group in obj.groups.all()
92
        ])
93

94

95
@admin.register(Integration)
4✔
96
class IntegrationAdmin(admin.ModelAdmin):
4✔
97
    search_fields = ('project__title', 'provider_key')
4✔
98
    list_display = ('project', 'provider_key')
4✔
99

100

101
@admin.register(IntegrationOption)
4✔
102
class IntegrationOptionAdmin(admin.ModelAdmin):
4✔
103
    search_fields = ('integration__project__title', 'key', 'value')
4✔
104
    list_display = ('integration', 'key', 'value')
4✔
105

106

107
@admin.register(Invite)
4✔
108
class InviteAdmin(admin.ModelAdmin):
4✔
109
    search_fields = ('project__title', 'user__username', 'email', 'role')
4✔
110
    list_display = ('project', 'user', 'email', 'token', 'timestamp')
4✔
111
    readonly_fields = ('token', 'timestamp')
4✔
112

113

114
@admin.register(Issue)
4✔
115
class IssueAdmin(admin.ModelAdmin):
4✔
116
    search_fields = ('project__title', 'task', 'status')
4✔
117
    list_display = ('project', 'task', 'status')
4✔
118
    list_filter = ('status', )
4✔
119

120

121
@admin.register(IssueResource)
4✔
122
class IssueResourceAdmin(admin.ModelAdmin):
4✔
123
    search_fields = ('issue__project__title', 'url')
4✔
124
    list_display = ('issue', 'url')
4✔
125

126

127
@admin.register(Snapshot)
4✔
128
class SnapshotAdmin(admin.ModelAdmin):
4✔
129
    search_fields = ('title', 'project__title', 'project__user__username')
4✔
130
    list_display = ('title', 'project_title', 'project_owners', 'updated', 'created')
4✔
131

132
    def get_queryset(self, request):
4✔
133
        return Snapshot.objects.prefetch_related(
×
134
            Prefetch(
135
                'project__memberships',
136
                queryset=Membership.objects.filter(role='owner').select_related('user'),
137
                to_attr='owner_memberships'
138
            )
139
        ).select_related('project')
140

141
    def project_title(self, obj):
4✔
142
        url = reverse('admin:projects_project_change', args=[obj.project.id])
×
143
        link = f'<a href="{url}">{obj.project.title}</a>'
×
144
        return mark_safe(link)
×
145

146
    def project_owners(self, obj):
4✔
147
        return [membership.user.get_full_name() for membership in obj.project.owner_memberships]
×
148

149

150
@admin.register(Value)
4✔
151
class ValueAdmin(admin.ModelAdmin):
4✔
152
    search_fields = ('attribute__uri', 'project__title', 'snapshot__title', 'project__user__username')
4✔
153
    list_display = ('attribute', 'set_prefix', 'set_index', 'collection_index', 'set_collection', 'value_type',
4✔
154
                    'project_title', 'project_owners', 'snapshot_title', 'updated', 'created')
155
    list_filter = ('value_type', )
4✔
156

157
    def get_queryset(self, request):
4✔
158
        return Value.objects.prefetch_related(
×
159
            Prefetch(
160
                'project__memberships',
161
                queryset=Membership.objects.filter(role='owner').select_related('user'),
162
                to_attr='owner_memberships'
163
            )
164
        ).select_related('attribute', 'project', 'snapshot')
165

166
    def snapshot_title(self, obj):
4✔
167
        if obj.snapshot:
×
168
            return obj.snapshot.title
×
169

170
    def project_title(self, obj):
4✔
171
        url = reverse('admin:projects_project_change', args=[obj.project.id])
×
172
        link = f'<a href="{url}">{obj.project.title}</a>'
×
173
        return mark_safe(link)
×
174

175
    def project_owners(self, obj):
4✔
176
        return [membership.user.get_full_name() for membership in obj.project.owner_memberships]
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc