Source code for derrida.people.models

from django.db import models
from viapy.api import ViafEntity

from derrida.common.models import Named, Notable, DateRange
from derrida.places.models import Place


[docs]class AliasIntegerField(models.IntegerField): '''Alias field adapted from https://djangosnippets.org/snippets/10440/ to allow accessing an existing db field by a different name, both for user display and in model and queryset use. '''
[docs] def contribute_to_class(self, cls, name, virtual_only=False): super(AliasIntegerField, self).contribute_to_class(cls, name, virtual_only=True) setattr(cls, name, self)
def __get__(self, instance, instance_type=None): return getattr(instance, self.db_column) def __set__(self, instance, value, instance_type=None): return setattr(instance, self.db_column, value)
[docs]class Person(Notable, DateRange): '''Person''' authorized_name = models.CharField(max_length=255) viaf_id = models.URLField('VIAF id', null=True, blank=True) # alias start/end year from DateRange to be more readable and semantic birth = AliasIntegerField(db_column='start_year', null=True, blank=True) death = AliasIntegerField(db_column='end_year', null=True, blank=True) sort_name = models.CharField(max_length=255, blank=True) family_group = models.CharField(max_length=255, blank=True) relationships = models.ManyToManyField('self', through='Relationship', related_name='related_to', symmetrical=False) # NOTE: django doesn't allow many-to-many to self with a through # table to be symmetrical class Meta: verbose_name_plural = 'People' # should this sort on sort_name first before authorized name? # if not, why do we have it? ordering = ['authorized_name'] def __str__(self): return self.authorized_name
[docs] def save(self, *args, **kwargs): '''Adds birth and death dates from VIAF if they aren't set and there's a viaf id for the record''' if self.viaf_id and not self.birth and not self.death: self.set_birth_death_years() super(Person, self).save(*args, **kwargs)
@property def viaf(self): ''':class:`viapy.api.ViafEntity` for this record if :attr:`viaf_id` is set.''' if self.viaf_id: return ViafEntity(self.viaf_id)
[docs] def set_birth_death_years(self): '''Set local birth and death dates based on information from VIAF''' if self.viaf_id: self.birth = self.viaf.birthyear self.death = self.viaf.deathyear
@property def firstname_last(self): '''Authorized name in 'firstname lastname' format for display''' names = self.authorized_name.split(', ', 1) return ' '.join(reversed(names)) @property def lastname(self): '''Last name, as extracted from authorized name''' return self.authorized_name.split(', ', 1)[0] @property def firstname(self): '''First name, as extracted from authorized name''' return self.authorized_name.split(',', 1)[1].strip() if ',' in self.authorized_name else ''
[docs]class Residence(Notable, DateRange): '''A residence where a person lived at some point in time''' person = models.ForeignKey(Person) place = models.ForeignKey(Place) def __str__(self): dates = '' if self.dates: dates = ' (%s)' % self.dates return '%s %s%s' % (self.person, self.place, dates)
[docs]class RelationshipType(Named, Notable): '''Types of relationships between people''' is_symmetric = models.BooleanField(default=False)
[docs]class Relationship(Notable, DateRange): '''A specific relationship between two people.''' from_person = models.ForeignKey(Person, related_name='from_relationships') to_person = models.ForeignKey(Person, related_name='to_relationships') relationship_type = models.ForeignKey(RelationshipType) def __str__(self): return '%s %s %s' % (self.from_person, self.relationship_type, self.to_person)