Completed
Push — devel ( 3eb06e...2ff9b7 )
by Paolo
09:23 queued 07:51
created

image_app.admin.DictBreedAdmin.get_term()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nop 2
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
"""
4
Created on Wed Nov  7 11:54:15 2018
5
6
@author: Paolo Cozzi <[email protected]>
7
"""
8
9
from django import forms
10
from django.contrib import admin
11
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
12
from django.contrib.auth.models import User
13
14
from .models import (Animal, DictBreed, DictCountry, DictRole, DictSpecie,
15
                     Name, Ontology, Organization, Person, Publication, Sample,
16
                     Submission, DictSex, DictUberon, DictDevelStage,
17
                     DictPhysioStage)
18
19
20
class DictBreedAdmin(admin.ModelAdmin):
21
    search_fields = ['supplied_breed']
22
    list_per_page = 25
23
    list_display = (
24
        'supplied_breed', 'get_label', 'get_term', 'mapped_breed',
25
        'mapped_breed_term', 'confidence', 'country', 'specie')
26
27
    # override label and term verbose names
28
    def get_label(self, instance):
29
        return instance.label
30
    get_label.short_description = "label"
31
32
    def get_term(self, instance):
33
        return instance.term
34
    get_term.short_description = "term"
35
36
    list_filter = ('country', 'specie')
37
38
39
class NameAdmin(admin.ModelAdmin):
40
    """A class to deal with animal names"""
41
42
    search_fields = ['name', 'biosample_id']
43
44
    list_per_page = 25
45
    list_display = (
46
        'name', 'submission', 'biosample_id', 'owner', 'status',
47
        'last_changed', 'last_submitted')
48
49
    list_filter = ('owner', 'status')
50
51
    # join immediately name with DataSouce, in order to speed up name rendering
52
    list_select_related = (
53
        'submission', 'submission__gene_bank_country', 'owner'
54
    )
55
56
57
# redefine form to edit Sample. Link animal to names in order to speed up
58
# name rendering
59
class SampleAdminForm(forms.ModelForm):
60
    class Meta:
61
        model = Sample
62
        fields = '__all__'
63
64
    def __init__(self, *args, **kwargs):
65
        super(SampleAdminForm, self).__init__(*args, **kwargs)
66
67
        # This is the bit that matters:
68
        self.fields['animal'].queryset = Animal.objects.select_related('name')
69
70
71
# inspired from here:
72
# https://github.com/geex-arts/django-jet/issues/244#issuecomment-325001298
73
class SampleInLineFormSet(forms.BaseInlineFormSet):
74
    ''' Base Inline formset for Sample Model'''
75
76
    def __init__(self, *args, **kwargs):
77
        super(SampleInLineFormSet, self).__init__(*args, **kwargs)
78
79
        # Animal will be a Animal object called when editing animal
80
        animal = kwargs["instance"]
81
82
        # get all Sample names from a certain animal with a unique query
83
        # HINT: all problems related to subquery when displaying names arise
84
        # from my __str__s methods, which display Sample and Animal name
85
        # and the relation between table Name. In order to have all sample
86
        # names for each animal, I need a join with three tables
87
        self.queryset = Sample.objects.select_related(
88
            'animal').select_related(
89
                'name').filter(animal=animal)
90
91
92
class SampleInline(admin.StackedInline):
93
    formset = SampleInLineFormSet
94
95
    fields = (
96
        ('name', 'alternative_id', 'description', 'owner'),
97
        ('animal', 'protocol', 'organism_part'),
98
        ('collection_date', 'collection_place_latitude',
99
         'collection_place_longitude', 'collection_place'),
100
        ('developmental_stage', 'physiological_stage',
101
         'animal_age_at_collection', 'animal_age_at_collection_units',
102
         'availability'),
103
        ('storage', 'storage_processing', 'preparation_interval',
104
         'preparation_interval_units')
105
    )
106
107
    # manage a fields with many FK keys
108
    # https://books.agiliq.com/projects/django-admin-cookbook/en/latest/many_fks.html
109
    raw_id_fields = ("name", "animal")
110
111
    model = Sample
112
    extra = 0
113
114
115
class SampleAdmin(admin.ModelAdmin):
116
    form = SampleAdminForm
117
118
    # exclude = ('author',)
119
    # prepopulated_fields = {'name': ['description']}
120
    search_fields = ['name__name']
121
    list_per_page = 25
122
    list_display = (
123
        'name', 'alternative_id', 'animal',
124
        'protocol', 'collection_date', 'collection_place_latitude',
125
        'collection_place_longitude', 'collection_place', 'organism_part',
126
        'developmental_stage', 'physiological_stage',
127
        'animal_age_at_collection', 'animal_age_at_collection_units',
128
        'availability', 'storage', 'storage_processing',
129
        'preparation_interval', 'preparation_interval_units', 'description',
130
        'owner'
131
    )
132
133
    # To tell Django we want to perform a join instead of fetching the names of
134
    # the categories one by one
135
    list_select_related = ('name', 'animal__name', 'owner', 'organism_part')
136
137
    list_filter = ('owner', 'name__status')
138
139
    fields = (
140
        ('name', 'alternative_id', 'description', 'owner'),
141
        ('animal', 'protocol', 'organism_part'),
142
        ('collection_date', 'collection_place', 'collection_place_latitude',
143
         'collection_place_longitude', 'collection_place_accuracy'),
144
        ('developmental_stage',
145
         'physiological_stage', 'animal_age_at_collection',
146
         'animal_age_at_collection_units', 'availability'),
147
        ('storage', 'storage_processing', 'preparation_interval',
148
         'preparation_interval_units')
149
    )
150
151
    # manage a fields with many FK keys
152
    # https://books.agiliq.com/projects/django-admin-cookbook/en/latest/many_fks.html
153
    raw_id_fields = ("name", "animal")
154
155
156
class AnimalAdmin(admin.ModelAdmin):
157
    search_fields = ['name__name']
158
159
    list_per_page = 25
160
    list_display = (
161
        'name', 'alternative_id', 'breed', 'sex',
162
        'father', 'mother', 'birth_location', 'birth_location_latitude',
163
        'birth_location_longitude', 'description', 'owner'
164
        )
165
166
    list_filter = ('owner', 'name__status')
167
168
    fields = (
169
        'name', 'alternative_id', 'breed', 'sex', 'father',
170
        'mother', ('birth_location', 'birth_location_latitude',
171
                   'birth_location_longitude'),
172
        'description', 'owner'
173
        )
174
175
    # I can add manually an item if it is a readonly field
176
    # readonly_fields = ("name",)
177
178
    # manage a fields with many FK keys
179
    # https://books.agiliq.com/projects/django-admin-cookbook/en/latest/many_fks.html
180
    raw_id_fields = ("name", "father", "mother", "breed")
181
182
    # https://medium.com/@hakibenita/things-you-must-know-about-django-admin-as-your-app-gets-bigger-6be0b0ee9614
183
    list_select_related = (
184
        'name', 'breed', 'breed__specie', 'sex', 'father', 'mother', 'owner')
185
186
    inlines = [SampleInline]
187
188
189
class SubmissionAdmin(admin.ModelAdmin):
190
    list_per_page = 25
191
    list_display = (
192
        'title', 'description', 'gene_bank_name', 'gene_bank_country',
193
        'datasource_type', 'datasource_version', 'organization', 'created_at',
194
        'updated_at', 'status', 'owner'
195
    )
196
197
    # I cannot edit a auto_add_now field
198
    readonly_fields = ('created_at', 'updated_at')
199
200
    list_filter = ('owner', 'status')
201
202
203
class PersonAdmin(admin.ModelAdmin):
204
    list_per_page = 25
205
    list_display = (
206
        'user_name', 'full_name', 'initials', 'affiliation', 'role',
207
    )
208
209
    def user_name(self, obj):
210
        return obj.user.username
211
212
    # rename column in admin
213
    user_name.short_description = "User Name"
214
215
    def full_name(self, obj):
216
        return "%s %s" % (obj.user.first_name, obj.user.last_name)
217
218
    full_name.short_description = "Full Name"
219
220
221
# https://simpleisbetterthancomplex.com/tutorial/2016/11/23/how-to-add-user-profile-to-django-admin.html
222
class PersonInLine(admin.StackedInline):
223
    model = Person
224
    can_delete = False
225
    verbose_name_plural = 'Person'
226
    fk_name = 'user'
227
228
229
class UserAdmin(BaseUserAdmin):
230
    inlines = (PersonInLine, )
231
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff',
232
                    'get_role')
233
    list_select_related = ('person', )
234
235
    # this will display a column Role in User admin
236
    def get_role(self, instance):
237
        return instance.person.role
238
    get_role.short_description = 'Role'
239
240
    # display the inlines only in the edit form
241
    def get_inline_instances(self, request, obj=None):
242
        if not obj:
243
            return list()
244
        return super(UserAdmin, self).get_inline_instances(request, obj)
245
246
247
class OrganizationAdmin(admin.ModelAdmin):
248
    list_per_page = 25
249
    search_fields = ['name']
250
    list_display = (
251
        'name', 'address', 'country', 'URI', 'role',
252
    )
253
254
255
class OntologyAdmin(admin.ModelAdmin):
256
    list_per_page = 25
257
    search_fields = ['library_name']
258
    list_display = (
259
        'library_name', 'library_uri', 'comment',
260
    )
261
262
263
class DictCountryAdmin(admin.ModelAdmin):
264
    list_per_page = 25
265
    list_display = ('label', 'term', 'confidence')
266
267
268
class DictSpecieAdmin(admin.ModelAdmin):
269
    list_per_page = 25
270
    list_display = (
271
        'label', 'term', 'confidence', 'general_breed_label',
272
        'general_breed_term')
273
274
275
# --- registering applications
276
277
# default admin class
278
admin.site.register(DictRole, admin.ModelAdmin)
279
admin.site.register(DictSex, admin.ModelAdmin)
280
admin.site.register(DictUberon, admin.ModelAdmin)
281
admin.site.register(DictDevelStage, admin.ModelAdmin)
282
admin.site.register(DictPhysioStage, admin.ModelAdmin)
283
284
# Custom admin class
285
admin.site.register(DictSpecie, DictSpecieAdmin)
286
admin.site.register(DictCountry, DictCountryAdmin)
287
admin.site.register(Submission, SubmissionAdmin)
288
admin.site.register(Animal, AnimalAdmin)
289
admin.site.register(Sample, SampleAdmin)
290
admin.site.register(Name, NameAdmin)
291
admin.site.register(DictBreed, DictBreedAdmin)
292
admin.site.register(Person, PersonAdmin)
293
admin.site.register(Organization, OrganizationAdmin)
294
admin.site.register(Publication, admin.ModelAdmin)
295
admin.site.register(Ontology, OntologyAdmin)
296
297
# Re-register UserAdmin (to see related person data)
298
admin.site.unregister(User)
299
admin.site.register(User, UserAdmin)
300