Commit d2c24a3a authored by Nicolas Noé's avatar Nicolas Noé
Browse files

Better models, import script and admin.

parent c0656b37
from django.contrib import admin
from django import forms
from .models import Specimen
from .models import Specimen, SpecimenLocation, Person, Fixation
from .widgets import LatLongWidget
......@@ -19,4 +19,20 @@ class MyAdminForm(forms.ModelForm):
class SpecimenAdmin(admin.ModelAdmin):
form = MyAdminForm
list_display = ('specimen_id', 'scientific_name', 'identified_by', 'specimen_location', 'depth', 'fixation')
list_filter = ('identified_by', 'specimen_location', 'fixation')
search_fields = ['scientific_name']
class SpecimenLocationAdmin(admin.ModelAdmin):
pass
class PersonAdmin(admin.ModelAdmin):
pass
class FixationAdmin(admin.ModelAdmin):
pass
admin.site.register(Specimen, SpecimenAdmin)
admin.site.register(SpecimenLocation, SpecimenLocationAdmin)
admin.site.register(Person, PersonAdmin)
admin.site.register(Fixation, FixationAdmin)
\ No newline at end of file
import csv
from psycopg2.extras import NumericRange
from django.core.management.base import BaseCommand, CommandError
from django.contrib.gis.geos import Point
from specimens.models import Person, SpecimenLocation, Specimen
from specimens.models import Person, SpecimenLocation, Specimen, Fixation
MODELS_TO_TRUNCATE = [Fixation, Person, SpecimenLocation, Specimen]
# TODO: document use of this script:
# - export Google Sheet (specimens) as CSV (separator: comma)
......@@ -28,40 +32,49 @@ class Command(BaseCommand):
self.stdout.write('Importing data from file...')
with open(options['csv_file']) as csv_file:
if options['truncate']:
self.stdout.write('Truncate existing data...', ending='')
Person.objects.all().delete()
SpecimenLocation.objects.all().delete()
Specimen.objects.all().delete()
self.stdout.write(self.style.SUCCESS('OK'))
for model in MODELS_TO_TRUNCATE:
self.stdout.write('Truncate model {name} '.format(name=model.__name__), ending='')
model.objects.all().delete()
self.stdout.write(self.style.SUCCESS('OK'))
for i, row in enumerate(csv.DictReader(csv_file, delimiter=',')):
self.stdout.write('Processing row #{i}...'.format(i=i), ending='')
specimen = Specimen()
# Identificators
id_first_name, id_last_name = row['Identified_by'].split()
identificator, _ = Person.objects.get_or_create(first_name=id_first_name, last_name=id_last_name)
identified_by = row['Identified_by'].strip()
if identified_by:
id_first_name, id_last_name = identified_by.split()
identificator, _ = Person.objects.get_or_create(first_name=id_first_name, last_name=id_last_name)
specimen.identified_by = identificator
# Specimen locations
specimen_location, _ = SpecimenLocation.objects.get_or_create(name=row['Specimen_location'])
specimen = Specimen()
specimen.specimen_location = specimen_location
# Coordinates
if row['Latitude'] and row['Longitude']:
lat = float(row['Latitude'].replace(',','.'))
lon = float(row['Longitude'].replace(',','.'))
specimen.coords = Point(lon, lat)
# Fixation
fixation = row['Fixation'].strip()
if fixation:
specimen.fixation, _ = Fixation.objects.get_or_create(name=fixation)
specimen.comment = row['Comment']
if row['Depth']:
if '-' in row['Depth']: # It's a range
min, max = row['Depth'].split('-')
depth = row['Depth'].strip()
if depth:
if '-' in depth: # It's a range
d_min, d_max = depth.split('-')
else: # Single value
min = max = row['Depth']
d_min = d_max = depth
specimen.depth = (float(min.replace(',','.')), float(max.replace(',','.')))
specimen.depth = NumericRange(float(d_min.replace(',','.')), float(d_max.replace(',','.')), bounds='[]')
specimen.identified_by = identificator
specimen.scientific_name = row['Scientific_name']
specimen.specimen_id = row['Specimen_id']
specimen.save()
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.2 on 2017-06-15 10:51
# Generated by Django 1.11.2 on 2017-06-16 08:26
from __future__ import unicode_literals
import django.contrib.gis.db.models.fields
......@@ -16,6 +16,13 @@ class Migration(migrations.Migration):
]
operations = [
migrations.CreateModel(
name='Fixation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name='Person',
fields=[
......@@ -23,6 +30,9 @@ class Migration(migrations.Migration):
('first_name', models.CharField(max_length=100)),
('last_name', models.CharField(max_length=100)),
],
options={
'verbose_name_plural': 'people',
},
),
migrations.CreateModel(
name='Specimen',
......@@ -30,10 +40,11 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('specimen_id', models.IntegerField(unique=True)),
('scientific_name', models.CharField(max_length=100)),
('coords', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326)),
('depth', django.contrib.postgres.fields.ranges.FloatRangeField(blank=True, null=True)),
('coords', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326, verbose_name='Coordinates')),
('depth', django.contrib.postgres.fields.ranges.FloatRangeField(blank=True, help_text='Unit: meters.', null=True)),
('comment', models.TextField(blank=True, null=True)),
('identified_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='specimens.Person')),
('fixation', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='specimens.Fixation')),
('identified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='specimens.Person')),
],
),
migrations.CreateModel(
......
......@@ -7,17 +7,31 @@ class Person(models.Model):
class Meta:
unique_together = ("first_name", "last_name")
verbose_name_plural = "people"
def __str__(self):
return self.first_name + ' ' + self.last_name
class SpecimenLocation(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Fixation(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Specimen(models.Model):
specimen_id = models.IntegerField(unique=True) # ID from the lab, not Django's PK
scientific_name = models.CharField(max_length=100)
coords = models.PointField(blank=True, null=True)
depth = FloatRangeField(blank=True, null=True) # Waiting confirmation for unit and integer/float
identified_by = models.ForeignKey(Person)
coords = models.PointField("Coordinates", blank=True, null=True)
depth = FloatRangeField(blank=True, null=True, help_text="Unit: meters.")
identified_by = models.ForeignKey(Person, blank=True, null=True)
specimen_location = models.ForeignKey(SpecimenLocation)
fixation = models.ForeignKey(Fixation, blank=True, null=True)
comment = models.TextField(blank=True, null=True)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment