admin.py 9.28 KB
Newer Older
1
"""
2
iPPI-DB django admin module
3
"""
4
from django.apps import apps
Hervé  MENAGER's avatar
Hervé MENAGER committed
5
from django.contrib import admin
6
from django.contrib import messages
7
from django.contrib.admin.options import get_content_type_for_model
8
from django.contrib.auth import get_user_model
9
10
11
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
12
from django.db.models import Q
13
from django.utils.html import format_html
14
from django.utils.translation import ugettext, ugettext_lazy
15

16
17
18
19
20
21
22
23
24
25
26
27
28
29
from .models import (
    Bibliography,
    Protein,
    Taxonomy,
    Domain,
    reverse,
    ProteinDomainBoundComplex,
    ProteinDomainPartnerComplex,
    Symmetry,
    Compound,
    TestActivityDescription,
    Ppi,
    ProteinDomainComplex,
    Contribution,
30
    Job,
31
)
32
from .tasks import launch_validate_contributions
33
from django.urls import reverse
Hervé  MENAGER's avatar
Hervé MENAGER committed
34

Hervé  MENAGER's avatar
Hervé MENAGER committed
35

36
37
class ViewOnSiteModelAdmin(admin.ModelAdmin):
    class Media:
Hervé  MENAGER's avatar
Hervé MENAGER committed
38
        js = ("/static/font-awesome/js/all.min.js",)
39
40

    def __init__(self, model, admin_site):
41
42
43
44
        if callable(getattr(model, "get_absolute_url", None)) and callable(
            self.view_on_site_in_list
        ):
            self.list_display += ("view_on_site_in_list",)
45
46
47
48
        super().__init__(model, admin_site)

    def view_on_site_in_list(self, obj):
        return format_html(
49
50
51
52
53
54
55
56
            '<center><a href="'
            + reverse(
                "admin:view_on_site",
                kwargs={
                    "content_type_id": get_content_type_for_model(obj).pk,
                    "object_id": obj.pk,
                },
            )
57
            + '"><i class="fa fa-external-link-alt"></i></a><center>'
58
        )
59

60
61
62
    view_on_site_in_list.short_description = format_html(
        "<center>" + ugettext("View on site") + "<center>"
    )
63
64


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
@admin.register(Job)
class JobModelAdmin(admin.ModelAdmin):
    date_hierarchy = "task_result__date_done"
    list_display = (
        "task_result_task_name",
        "task_result_task_id",
        "task_result_status",
        "task_result_date_created",
        "task_result_date_done",
    )
    list_filter = (
        "task_result__status",
        "task_result__date_done",
        "task_result__task_name",
    )
    readonly_fields = (
        "task_result_task_name",
        "task_result_task_id",
        "task_result_status",
        "task_result_date_created",
        "task_result_date_done",
    )
    search_fields = (
        "task_result__task_name",
        "task_result__task_id",
        "task_result__status",
    )
    fields = (
        ("task_result_task_name", "task_result_task_id"),
        "task_result_status",
        ("task_result_date_created", "task_result_date_done"),
        ("std_out", "std_err"),
    )

    def task_result_task_id(self, x):
        return x.task_result.task_id

    def task_result_task_name(self, x):
        return x.task_result.task_name

    def task_result_date_done(self, x):
        return x.task_result.date_done

    def task_result_status(self, x):
        return x.task_result.status

    def task_result_date_created(self, x):
        return x.task_result.date_created

    # def task_link(self, x):
    #    href = reverse("admin:task-results", args=[x.task_result.id])
    #    print(href)
    #    return '<a href="/admin/django_celery_results/taskresult/{}/change/">{}</a>'.format(x.task_result.id, x.task_result.task_id)
    
    # task_link.allow_tags = True
    task_result_task_id.short_description = "task_id"
    task_result_task_name.short_description = "task_name"
    task_result_date_done.short_description = "date_done"
    task_result_status.short_description = "status"
    task_result_date_created.short_description = "date_created"


127
@admin.register(Bibliography)
128
class BibliographyModelAdmin(ViewOnSiteModelAdmin):
129
    list_display = ("authors_list", "title", "journal_name", "biblio_year", "id_source")
Hervé  MENAGER's avatar
Hervé MENAGER committed
130

131

132
@admin.register(Protein)
133
class ProteinModelAdmin(admin.ModelAdmin):
134
135
    list_display = ("uniprot_id", "recommended_name_long")
    filter_horizontal = ("molecular_functions", "domains")
Bryan  BRANCOTTE's avatar
Bryan BRANCOTTE committed
136
    search_fields = (
137
138
139
140
141
        "uniprot_id",
        "recommended_name_long",
        "short_name",
        "gene_name",
        "entry_name",
Bryan  BRANCOTTE's avatar
Bryan BRANCOTTE committed
142
    )
143
    list_filter = ("organism",)
144

Hervé  MENAGER's avatar
Hervé MENAGER committed
145

146
@admin.register(Taxonomy)
147
class TaxonomyModelAdmin(admin.ModelAdmin):
148
    list_display = ("taxonomy_id", "name")
149

Hervé  MENAGER's avatar
Hervé MENAGER committed
150

151
@admin.register(Domain)
152
class DomainModelAdmin(admin.ModelAdmin):
153
    list_display = ("pfam_acc", "pfam_id", "pfam_description", "domain_family")
154

Hervé  MENAGER's avatar
Hervé MENAGER committed
155

156
@admin.register(ProteinDomainBoundComplex)
157
class ProteinDomainBoundComplexModelAdmin(ViewOnSiteModelAdmin):
158
159
    list_display = ("protein", "domain", "ppc_copy_nb", "ppp_copy_nb_per_p")
    list_display_links = ("protein", "domain", "ppc_copy_nb", "ppp_copy_nb_per_p")
Hervé  MENAGER's avatar
Hervé MENAGER committed
160

161
162

@admin.register(ProteinDomainPartnerComplex)
163
class ProteinDomainPartnerComplexModelAdmin(ViewOnSiteModelAdmin):
164
165
    list_display = ("protein", "domain", "ppc_copy_nb")
    list_display_links = ("protein", "domain", "ppc_copy_nb")
166

Hervé  MENAGER's avatar
Hervé MENAGER committed
167

168
@admin.register(Symmetry)
169
class SymmetryModelAdmin(admin.ModelAdmin):
170
    list_display = ("code", "description")
171

Hervé  MENAGER's avatar
Hervé MENAGER committed
172

173
@admin.register(Compound)
174
class CompoundModelAdmin(ViewOnSiteModelAdmin):
Hervé  MENAGER's avatar
Hervé MENAGER committed
175
176
177
178
179
180
181
    list_display = (
        "id",
        "iupac_name",
        "common_name",
        "canonical_smile",
        "is_validated",
    )
182
    search_fields = ("id", "iupac_name", "common_name", "canonical_smile")
183

Hervé  MENAGER's avatar
Hervé MENAGER committed
184

185
@admin.register(Contribution)
186
class ContributionModelAdmin(ViewOnSiteModelAdmin):
187
188
189
190
191
192
    list_display = (
        "id",
        "ppi",
        "bibliography",
        "validated",
        "created_at",
Hervé  MENAGER's avatar
Hervé MENAGER committed
193
        "updated_at",
194
    )
195
    search_fields = ("id", "ppi", "bibliography")
Hervé  MENAGER's avatar
Hervé MENAGER committed
196

197
198
199
200
    actions = ["validate_contributions"]

    def validate_contributions(self, request, queryset):
        ids = [id for id in queryset.values_list("id", flat=True)]
201
        launch_validate_contributions.delay(ids)
202
203
        self.message_user(
            request,
204
205
206
            f"validation started for contributions(s) "
            f"{','.join(str(id) for id in queryset.values_list('id', flat=True))}"
            f" (this might take a while).",
207
208
        )

Hervé  MENAGER's avatar
Hervé MENAGER committed
209

210
@admin.register(TestActivityDescription)
211
class TextActivityDescriptionModelAdmin(ViewOnSiteModelAdmin):
212
    list_display = ("test_name", "test_type", "test_modulation_type")
213

214

215
@admin.register(Ppi)
216
class PpiModelAdmin(ViewOnSiteModelAdmin):
217
218
219
220
    filter_horizontal = ("diseases",)
    list_display = ("pdb_id", "name", "symmetry", "family")
    list_filter = ("diseases",)
    search_fields = ("pdb_id", "name", "symmetry", "family__name", "diseases__name")
221
222


223
@admin.register(ProteinDomainComplex)
224
class ProteinDomainComplexModelAdmin(ViewOnSiteModelAdmin):
225
226
227
228
229
230
231
232
    search_fields = (
        "id",
        "protein__id",
        "domain__id",
        "protein__uniprot_id",
        "domain__pfam_acc",
    )
    list_display = ("id", "__str__", "protein_uniprot_id", "domain_pfam_acc")
233
234

    def protein_uniprot_id(self, o):
235
        return o.protein.uniprot_id if o.protein is not None else None
236

237
238
    protein_uniprot_id.short_description = "protein"
    protein_uniprot_id.admin_order_field = "protein__uniprot_id"
239
240

    def domain_pfam_acc(self, o):
241
        return o.domain.pfam_acc if o.domain is not None else None
242

243
244
    domain_pfam_acc.short_description = "Domain"
    domain_pfam_acc.admin_order_field = "domain__pfam_acc"
245
246


247
for model in apps.get_app_config("ippidb").models.values():
248
    try:
249
        admin.site.register(model, ViewOnSiteModelAdmin)
250
    except admin.sites.AlreadyRegistered:
251
        continue
252

253
254
255
256

def grant_contribution_permission(modeladmin, request, queryset, revoke=False):
    content_type = ContentType.objects.get_for_model(Contribution)
    permission = Permission.objects.get(
257
        codename="add_contribution", content_type=content_type
258
259
260
261
262
263
264
265
266
    )
    for o in queryset:
        if revoke:
            o.user_permissions.remove(permission)
        else:
            o.user_permissions.add(permission)

    pointless = queryset.filter(Q(Q(is_superuser=True) | Q(is_staff=True))).count()
    count = queryset.count()
267
    msg = "Permission %s for %i user(s). "
268
269
270
271
272
273

    if revoke:
        msg = msg % ("revoked", count - pointless)
    else:
        msg = msg % ("granted", count - pointless)

274
275
276
    if modeladmin is None:
        return

277
278
279
280
281
    modeladmin.message_user(request, msg, messages.SUCCESS)

    if pointless:
        modeladmin.message_user(
            request,
282
283
            "Note that %i users are staff/superuser and thus always have the permission to contribute"
            % pointless,
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
            messages.WARNING,
        )


grant_contribution_permission.short_description = ugettext_lazy(
    "Grant permission to contribute"
)


def revoke_contribution_permission(modeladmin, request, queryset, revoke=False):
    grant_contribution_permission(modeladmin, request, queryset, True)


revoke_contribution_permission.short_description = ugettext_lazy(
    "Revoke permission to contribute"
)


class MyUserAdmin(UserAdmin):
303
304
305
306
307
308
309
310
311
    actions = [grant_contribution_permission, revoke_contribution_permission]
    list_display = (
        "username",
        "email",
        "first_name",
        "last_name",
        "is_staff",
        "can_contribute",
    )
312
313

    def can_contribute(self, object):
314
        return object.has_perm("ippidb.add_contribution")
315
316
317
318
319

    can_contribute.boolean = True


admin.site.unregister(get_user_model())
320
admin.site.register(get_user_model(), MyUserAdmin)