ENH: Sex fields as lookups (#55)

This commit is contained in:
Matthew Ryan Dillon 2018-03-03 12:10:17 -07:00 committed by GitHub
parent 4cd133f993
commit c52d4e736d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 182 additions and 9 deletions

View file

@ -35,6 +35,7 @@ router.register(r'sites', locations_viewsets.SiteViewSet)
router.register(r'study-locations', locations_viewsets.StudyLocationViewSet) router.register(r'study-locations', locations_viewsets.StudyLocationViewSet)
# Species # Species
router.register(r'species', species_viewsets.SpeciesViewSet) router.register(r'species', species_viewsets.SpeciesViewSet)
router.register(r'sexes', species_viewsets.SexViewSet)
router.register(r'collection-species', router.register(r'collection-species',
species_viewsets.CollectionSpeciesViewSet) species_viewsets.CollectionSpeciesViewSet)

View file

@ -1,6 +1,6 @@
from django.contrib import admin from django.contrib import admin
from .models import Species, TrapSpecies, CollectionSpecies from .models import Species, Sex, TrapSpecies, CollectionSpecies
class SpeciesAdmin(admin.ModelAdmin): class SpeciesAdmin(admin.ModelAdmin):
@ -12,6 +12,14 @@ class SpeciesAdmin(admin.ModelAdmin):
fields = ('common_name', 'genus', 'species', 'parasite', 'sort_order') fields = ('common_name', 'genus', 'species', 'parasite', 'sort_order')
class SexAdmin(admin.ModelAdmin):
list_display = ('name', 'sort_order')
list_display_links = ('name',)
search_fields = ('name',)
list_per_page = 25
fields = ('name', 'sort_order')
class TrapSpeciesAdmin(admin.ModelAdmin): class TrapSpeciesAdmin(admin.ModelAdmin):
list_display = ('collection_trap', 'species', 'sex', 'count', list_display = ('collection_trap', 'species', 'sex', 'count',
'count_estimated') 'count_estimated')
@ -32,5 +40,6 @@ class CollectionSpeciesAdmin(admin.ModelAdmin):
admin.site.register(Species, SpeciesAdmin) admin.site.register(Species, SpeciesAdmin)
admin.site.register(Sex, SexAdmin)
admin.site.register(TrapSpecies, TrapSpeciesAdmin) admin.site.register(TrapSpecies, TrapSpeciesAdmin)
admin.site.register(CollectionSpecies, CollectionSpeciesAdmin) admin.site.register(CollectionSpecies, CollectionSpeciesAdmin)

View file

@ -0,0 +1,39 @@
from django.db import migrations, models
from django.forms import modelform_factory
class Migration(migrations.Migration):
def migrate(apps, schema_editor):
Sex = apps.get_model('species', 'Sex')
SexForm = modelform_factory(Sex, fields=('name', 'sort_order'))
for i, s in enumerate(['male', 'female', 'mixed', 'unknown']):
form = SexForm(dict(name=s, sort_order=i))
if form.is_valid():
form.save()
else:
print('sex', form.errors.as_data())
def rollback(apps, schema_editor):
Sex = apps.get_model('species', 'Sex')
Sex.objects.all().delete()
dependencies = [
('species', '0003_DATA_reset_sequences'),
]
operations = [
migrations.CreateModel(
name='Sex',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True,
serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=25, unique=True)),
('sort_order', models.IntegerField(blank=True, null=True)),
],
options={
'verbose_name_plural': 'sex',
'ordering': ['sort_order'],
},
),
migrations.RunPython(migrate, rollback),
]

View file

@ -0,0 +1,68 @@
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
def migrate(apps, schema_editor):
Sex = apps.get_model('species', 'Sex')
CollectionSpecies = apps.get_model('species', 'CollectionSpecies')
for cs in CollectionSpecies.objects.all():
if cs.old_sex:
if cs.old_sex == 'both':
s = 'mixed'
elif cs.old_sex not in ['male', 'female', 'mixed', 'unknown']:
s = 'unknown'
else:
s = cs.old_sex
cs.sex = Sex.objects.get(name=s)
cs.save()
def rollback(apps, schema_editor):
CollectionSpecies = apps.get_model('species', 'CollectionSpecies')
for cs in CollectionSpecies.objects.all():
if cs.sex:
cs.sex = None
cs.old_sex = ''
cs.save()
dependencies = [
('species', '0004_sex'),
]
operations = [
migrations.RenameField(
model_name='collectionspecies',
old_name='sex',
new_name='old_sex',
),
migrations.RenameField(
model_name='trapspecies',
old_name='sex',
new_name='old_sex',
),
migrations.AddField(
model_name='collectionspecies',
name='sex',
field=models.ForeignKey(
null=True, on_delete=django.db.models.deletion.CASCADE,
related_name='collection_species', to='species.Sex'),
),
migrations.AddField(
model_name='trapspecies',
name='sex',
field=models.ForeignKey(
null=True, on_delete=django.db.models.deletion.CASCADE,
related_name='trap_species', to='species.Sex'),
),
migrations.RunPython(migrate, rollback),
migrations.RemoveField(
model_name='collectionspecies',
name='old_sex',
),
migrations.RemoveField(
model_name='trapspecies',
name='old_sex',
),
]

View file

@ -17,13 +17,26 @@ class Species(models.Model):
verbose_name_plural = 'species' verbose_name_plural = 'species'
class Sex(models.Model):
name = models.CharField(max_length=25, unique=True)
sort_order = models.IntegerField(blank=True, null=True)
def __str__(self):
return self.name
class Meta:
ordering = ['sort_order']
verbose_name_plural = 'sex'
class TrapSpecies(models.Model): class TrapSpecies(models.Model):
collection_trap = models.ForeignKey('collections_ccdb.CollectionTrap', collection_trap = models.ForeignKey('collections_ccdb.CollectionTrap',
related_name='trap_species', related_name='trap_species',
on_delete=models.CASCADE) on_delete=models.CASCADE)
species = models.ForeignKey(Species, related_name='trap_species', species = models.ForeignKey(Species, related_name='trap_species',
on_delete=models.CASCADE) on_delete=models.CASCADE)
sex = models.CharField(max_length=25, blank=True) sex = models.ForeignKey(Sex, related_name='trap_species',
on_delete=models.CASCADE, null=True)
count = models.IntegerField(blank=True, null=True) count = models.IntegerField(blank=True, null=True)
count_estimated = models.BooleanField(default=False) count_estimated = models.BooleanField(default=False)
@ -40,7 +53,8 @@ class CollectionSpecies(models.Model):
on_delete=models.CASCADE) on_delete=models.CASCADE)
species = models.ForeignKey(Species, related_name='collection_species', species = models.ForeignKey(Species, related_name='collection_species',
on_delete=models.CASCADE) on_delete=models.CASCADE)
sex = models.CharField(max_length=25, blank=True) sex = models.ForeignKey(Sex, related_name='collection_species',
on_delete=models.CASCADE, null=True)
count = models.IntegerField(blank=True, null=True) count = models.IntegerField(blank=True, null=True)
count_estimated = models.BooleanField(default=False) count_estimated = models.BooleanField(default=False)

View file

@ -1,6 +1,6 @@
from rest_framework_json_api import serializers from rest_framework_json_api import serializers
from .models import Species, CollectionSpecies from .models import Species, Sex, CollectionSpecies
class SpeciesSerializer(serializers.ModelSerializer): class SpeciesSerializer(serializers.ModelSerializer):
@ -9,10 +9,17 @@ class SpeciesSerializer(serializers.ModelSerializer):
fields = ('common_name', 'genus', 'species', 'parasite', 'sort_order') fields = ('common_name', 'genus', 'species', 'parasite', 'sort_order')
class SexSerializer(serializers.ModelSerializer):
class Meta:
model = Sex
fields = ('name', 'sort_order')
class CollectionSpeciesSerializer(serializers.ModelSerializer): class CollectionSpeciesSerializer(serializers.ModelSerializer):
included_serializers = { included_serializers = {
'collection': 'ccdb.collections_ccdb.serializers.CollectionSerializer', 'collection': 'ccdb.collections_ccdb.serializers.CollectionSerializer',
'species': 'ccdb.species.serializers.SpeciesSerializer', 'species': 'ccdb.species.serializers.SpeciesSerializer',
'sex': 'ccdb.species.serializers.SexSerializer',
} }
class Meta: class Meta:

View file

@ -1,7 +1,7 @@
from factory import DjangoModelFactory, Sequence, SubFactory from factory import DjangoModelFactory, Sequence, SubFactory
from factory.fuzzy import FuzzyText, FuzzyChoice, FuzzyInteger from factory.fuzzy import FuzzyText, FuzzyChoice, FuzzyInteger
from ..models import Species, TrapSpecies, CollectionSpecies from ..models import Species, Sex, TrapSpecies, CollectionSpecies
from ccdb.collections_ccdb.tests.factories import (CollectionFactory, from ccdb.collections_ccdb.tests.factories import (CollectionFactory,
CollectionTrapFactory) CollectionTrapFactory)
@ -17,13 +17,21 @@ class SpeciesFactory(DjangoModelFactory):
sort_order = Sequence(lambda n: n) sort_order = Sequence(lambda n: n)
class SexFactory(DjangoModelFactory):
class Meta:
model = Sex
name = Sequence(lambda n: 'sex{}'.format(n))
sort_order = Sequence(lambda n: n)
class TrapSpeciesFactory(DjangoModelFactory): class TrapSpeciesFactory(DjangoModelFactory):
class Meta: class Meta:
model = TrapSpecies model = TrapSpecies
collection_trap = SubFactory(CollectionTrapFactory) collection_trap = SubFactory(CollectionTrapFactory)
species = SubFactory(SpeciesFactory) species = SubFactory(SpeciesFactory)
sex = FuzzyText(length=25) sex = SubFactory(SexFactory)
count = FuzzyInteger(0) count = FuzzyInteger(0)
count_estimated = FuzzyChoice(choices=[True, False]) count_estimated = FuzzyChoice(choices=[True, False])
@ -34,6 +42,6 @@ class CollectionSpeciesFactory(DjangoModelFactory):
collection = SubFactory(CollectionFactory) collection = SubFactory(CollectionFactory)
species = SubFactory(SpeciesFactory) species = SubFactory(SpeciesFactory)
sex = FuzzyText(length=25) sex = SubFactory(SexFactory)
count = FuzzyInteger(0) count = FuzzyInteger(0)
count_estimated = FuzzyChoice(choices=[True, False]) count_estimated = FuzzyChoice(choices=[True, False])

View file

@ -1,7 +1,8 @@
from rest_framework import viewsets from rest_framework import viewsets
from .models import Species, CollectionSpecies from .models import Species, Sex, CollectionSpecies
from .serializers import SpeciesSerializer, CollectionSpeciesSerializer from .serializers import (SpeciesSerializer, SexSerializer,
CollectionSpeciesSerializer)
class SpeciesViewSet(viewsets.ModelViewSet): class SpeciesViewSet(viewsets.ModelViewSet):
@ -9,6 +10,11 @@ class SpeciesViewSet(viewsets.ModelViewSet):
serializer_class = SpeciesSerializer serializer_class = SpeciesSerializer
class SexViewSet(viewsets.ModelViewSet):
queryset = Sex.objects.all()
serializer_class = SexSerializer
class CollectionSpeciesViewSet(viewsets.ModelViewSet): class CollectionSpeciesViewSet(viewsets.ModelViewSet):
queryset = CollectionSpecies.objects.all() queryset = CollectionSpecies.objects.all()
serializer_class = CollectionSpeciesSerializer serializer_class = CollectionSpeciesSerializer

View file

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.9 on 2018-02-28 12:46
from __future__ import unicode_literals
import django.contrib.auth.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0003_remove_user_timezone'),
]
operations = [
migrations.AlterField(
model_name='user',
name='username',
field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username'),
),
]