class Emplacement(models.Model, BaseModel, SourcesMixin, SuperlativeDateMixin, GetComplexFieldNameMixin): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.startdate = ComplexFieldContainer(self, EmplacementStartDate) self.enddate = ComplexFieldContainer(self, EmplacementEndDate) self.realstart = ComplexFieldContainer(self, EmplacementRealStart) self.open_ended = ComplexFieldContainer(self, EmplacementOpenEnded) self.organization = ComplexFieldContainer(self, EmplacementOrganization) self.site = ComplexFieldContainer(self, EmplacementSite) self.aliases = ComplexFieldListContainer(self, EmplacementAlias) self.complex_fields = [ self.startdate, self.enddate, self.organization, self.site, self.open_ended, self.realstart ] self.complex_lists = [self.aliases] self.required_fields = [ "Emplacement_EmplacementOrganization", "Emplacement_EmplacementSite", ] def get_value(self): return '{0} ({1})'.format(self.organization.get_value(), self.site.get_value())
class Composition(models.Model, BaseModel, SourcesMixin, GetComplexFieldNameMixin): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.parent = ComplexFieldContainer(self, CompositionParent) self.child = ComplexFieldContainer(self, CompositionChild) self.startdate = ComplexFieldContainer(self, CompositionStartDate) self.realstart = ComplexFieldContainer(self, CompositionRealStart) self.enddate = ComplexFieldContainer(self, CompositionEndDate) self.open_ended = ComplexFieldContainer(self, CompositionOpenEnded) self.classification = ComplexFieldContainer(self, CompositionClassification) self.complex_fields = [ self.parent, self.child, self.startdate, self.realstart, self.enddate, self.open_ended, self.classification ] self.complex_lists = [] self.required_fields = [ "Composition_CompositionParent", "Composition_CompositionChild" ] def get_value(self): return '{0} parent of {1}'.format(self.parent.get_value(), self.child.get_value())
class Geosite(models.Model, BaseModel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.name = ComplexFieldContainer(self, GeositeName) # OSM Name/ID of the smallest containing administrative unit self.admin_name = ComplexFieldContainer(self, GeositeAdminName) self.admin_id = ComplexFieldContainer(self, GeositeAdminId) # Larger administrative units (name only) self.adminlevel1 = ComplexFieldContainer(self, GeositeAdminLevel1) self.adminlevel2 = ComplexFieldContainer(self, GeositeAdminLevel2) # Coordinates and OSM Name/ID of the exact location self.coordinates = ComplexFieldContainer(self, GeositeCoordinates) self.location_name = ComplexFieldContainer(self, GeositeLocationName) self.location_id = ComplexFieldContainer(self, GeositeLocationId) self.division_id = ComplexFieldContainer(self, GeositeDivisionId) self.complex_fields = [ self.name, self.admin_name, self.admin_id, self.adminlevel1, self.adminlevel2, self.coordinates, self.location_name, self.location_id, self.division_id ] self.complex_lists = [] self.required_fields = ["Geosite_GeositeName"] def get_value(self): return self.name.get_value() def __str__(self): return str(self.name)
class Area(models.Model, BaseModel, GetComplexFieldNameMixin): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.name = ComplexFieldContainer(self, AreaName) self.code = ComplexFieldContainer(self, AreaCode) self.osmname = ComplexFieldContainer(self, AreaOSMName) self.osmid = ComplexFieldContainer(self, AreaOSMId) self.geometry = ComplexFieldContainer(self, AreaGeometry) self.division_id = ComplexFieldContainer(self, AreaDivisionId) self.complex_fields = [ self.name, self.code, self.osmname, self.geometry, self.division_id, self.osmid ] self.complex_lists = [] self.required_fields = [ "Area_AreaName", ] def get_value(self): return self.name.get_value() def __str__(self): return str(self.name) @classmethod def from_id(cls, id_): try: area = cls.objects.get(id=id_) return area except cls.DoesNotExist: return None
class Area(models.Model, BaseModel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.name = ComplexFieldContainer(self, AreaName) self.code = ComplexFieldContainer(self, AreaCode) self.osmname = ComplexFieldContainer(self, AreaOSMName) self.osmid = ComplexFieldContainer(self, AreaOSMId) self.geometry = ComplexFieldContainer(self, AreaGeometry) self.division_id = ComplexFieldContainer(self, AreaDivisionId) self.complex_fields = [self.name, self.code, self.osmname, self.geometry, self.division_id, self.osmid] self.complex_lists = [] self.required_fields = [ "Area_AreaName", ] def get_value(self): return self.name.get_value() def __str__(self): return str(self.name) @classmethod def from_id(cls, id_): try: area = cls.objects.get(id=id_) return area except cls.DoesNotExist: return None
class MembershipOrganization(models.Model, BaseModel, SourcesMixin, GetComplexFieldNameMixin): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.member = ComplexFieldContainer(self, MembershipOrganizationMember) self.organization = ComplexFieldContainer(self, MembershipOrganizationOrganization) self.firstciteddate = ComplexFieldContainer(self, MembershipOrganizationFirstCitedDate) self.realstart = ComplexFieldContainer(self, MembershipOrganizationRealStart) self.lastciteddate = ComplexFieldContainer(self, MembershipOrganizationLastCitedDate) self.open_ended = ComplexFieldContainer(self, MembershipOrganizationOpenEnded) self.complex_fields = [self.member, self.organization, self.firstciteddate, self.lastciteddate, self.realstart, self.open_ended] self.complex_lists = [] self.required_fields = [ "MembershipOrganization_MembershipOrganizationMember", "MembershipOrganization_MembershipOrganizationOrganization", ] @classmethod def from_id(cls, id_): try: membership = cls.objects.get(id=id_) return membership except cls.DoesNotExist: return None def get_value(self): return '{0} member of {1}'.format(self.member.get_value(), self.organization.get_value()) @classmethod def create(cls, dict_values, lang=get_language()): membership = cls() membership.update(dict_values, lang) return membership
class MembershipOrganization(models.Model, BaseModel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.member = ComplexFieldContainer(self, MembershipOrganizationMember) self.organization = ComplexFieldContainer(self, MembershipOrganizationOrganization) self.firstciteddate = ComplexFieldContainer(self, MembershipOrganizationFirstCitedDate) self.realstart = ComplexFieldContainer(self, MembershipOrganizationRealStart) self.lastciteddate = ComplexFieldContainer(self, MembershipOrganizationLastCitedDate) self.realend = ComplexFieldContainer(self, MembershipOrganizationRealEnd) self.complex_fields = [self.member, self.organization, self.firstciteddate, self.lastciteddate, self.realstart, self.realend] self.complex_lists = [] self.required_fields = [ "MembershipOrganization_MembershipOrganizationMember", "MembershipOrganization_MembershipOrganizationOrganization", ] @classmethod def from_id(cls, id_): try: membership = cls.objects.get(id=id_) return membership except cls.DoesNotExist: return None def get_value(self): return '{0} member of {1}'.format(self.member.get_value(), self.organization.get_value()) @classmethod def create(cls, dict_values, lang=get_language()): membership = cls() membership.update(dict_values, lang) return membership
class Composition(models.Model, BaseModel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.parent = ComplexFieldContainer(self, CompositionParent) self.child = ComplexFieldContainer(self, CompositionChild) self.startdate = ComplexFieldContainer(self, CompositionStartDate) self.realstart = ComplexFieldContainer(self, CompositionRealStart) self.enddate = ComplexFieldContainer(self, CompositionEndDate) self.open_ended = ComplexFieldContainer(self, CompositionOpenEnded) self.classification = ComplexFieldContainer(self, CompositionClassification) self.complex_fields = [self.parent, self.child, self.startdate, self.realstart, self.enddate, self.open_ended, self.classification] self.complex_lists = [] self.required_fields = [ "Composition_CompositionParent", "Composition_CompositionChild" ] def get_value(self): return '{0} parent of {1}'.format(self.parent.get_value(), self.child.get_value())
class Emplacement(models.Model, BaseModel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.startdate = ComplexFieldContainer(self, EmplacementStartDate) self.enddate = ComplexFieldContainer(self, EmplacementEndDate) self.realstart = ComplexFieldContainer(self, EmplacementRealStart) self.open_ended = ComplexFieldContainer(self, EmplacementOpenEnded) self.organization = ComplexFieldContainer(self, EmplacementOrganization) self.site = ComplexFieldContainer(self, EmplacementSite) self.aliases = ComplexFieldListContainer(self, EmplacementAlias) self.complex_fields = [self.startdate, self.enddate, self.organization, self.site, self.open_ended, self.realstart] self.complex_lists = [self.aliases] self.required_fields = [ "Emplacement_EmplacementOrganization", "Emplacement_EmplacementSite", ] def get_value(self): return '{0} ({1})'.format(self.organization.get_value(), self.site.get_value())
class Person(models.Model, BaseModel, VersionsMixin): uuid = models.UUIDField(default=uuid.uuid4, editable=False, db_index=True) published = models.BooleanField(default=False) def __init__(self, *args, **kwargs): self.name = ComplexFieldContainer(self, PersonName) self.aliases = ComplexFieldListContainer(self, PersonAlias) self.division_id = ComplexFieldContainer(self, PersonDivisionId) self.gender = ComplexFieldContainer(self, PersonGender) self.date_of_birth = ComplexFieldContainer(self, PersonDateOfBirth) self.date_of_death = ComplexFieldContainer(self, PersonDateOfDeath) self.deceased = ComplexFieldContainer(self, PersonDeceased) self.biography = ComplexFieldContainer(self, PersonBiography) self.notes = ComplexFieldContainer(self, PersonNotes) self.external_links = ComplexFieldListContainer(self, PersonExternalLink) self.complex_fields = [ self.name, self.division_id, self.gender, self.date_of_birth, self.date_of_death, self.deceased, self.biography, self.notes, ] self.complex_lists = [self.aliases, self.external_links] self.required_fields = [ "Person_PersonName", ] super().__init__(*args, **kwargs) def get_value(self): return self.name.get_value() def __str__(self): try: return str(self.personname_set.first().value) except AttributeError: return str(self.uuid) def get_absolute_url(self): return reverse('view-person', kwargs={'slug': self.uuid}) @cached_property def memberships(self): ''' Return all of this person's memberships, in a custom sorting order. Order by first cited date descending, then last cited date descending, with nulls last. ''' mems = self.membershippersonmember_set\ .select_related('object_ref')\ .annotate(lcd=Coalesce('object_ref__membershippersonfirstciteddate__value', 'object_ref__membershippersonlastciteddate__value', models.Value('1000-0-0')))\ .order_by('-lcd') return mems @property def last_cited(self): ''' Get the global last citation date for this person, leaving out nulls. ''' order = '-object_ref__membershippersonlastciteddate__value' memberships = self.membershippersonmember_set.order_by(order) for membership in memberships: # Filter nulls lcd = membership.object_ref.lastciteddate.get_value() if lcd: return lcd @property def first_cited(self): ''' Get the global first citation date for this person, leaving out nulls. ''' order = 'object_ref__membershippersonfirstciteddate__value' memberships = self.membershippersonmember_set.order_by(order) for membership in memberships: fcd = membership.object_ref.firstciteddate.get_value() if fcd: return fcd
class Area(models.Model, BaseModel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.name = ComplexFieldContainer(self, AreaName) self.code = ComplexFieldContainer(self, AreaCode) self.geoname = ComplexFieldContainer(self, AreaGeoName) self.geometry = ComplexFieldContainer(self, AreaGeometry) self.complex_fields = [ self.name, self.code, self.geoname, self.geometry ] self.required_fields = [ "Area_AreaName", ] def get_value(self): return self.name.get_value() def __str__(self): return str(self.name) @classmethod def from_id(cls, id_): try: area = cls.objects.get(id=id_) return area except cls.DoesNotExist: return None def validate(self, dict_values): errors = {} coordinates = dict_values['Area_AreaGeometry'].get("value") if coordinates: try: poly = geos.fromstr(coordinates) if not isinstance(poly, geos.Polygon): errors["Area_AreaGeometry"] = ( "The geometry must be a polygon, not a point") except TypeError: errors["Area_AreaGeometry"] = ("Invalid data for a polygon") (base_errors, values) = super().validate(dict_values) errors.update(base_errors) return (errors, values) @classmethod def search(cls, terms): order_by = terms.get('orderby') if not order_by: order_by = 'areaname__value' elif order_by in ['name']: order_by = 'area' + order_by + '__value' direction = terms.get('direction') if not direction: direction = 'ASC' dirsym = '' if direction == 'DESC': dirsym = '-' area_query = (Area.objects.annotate( Max(order_by)).order_by(dirsym + order_by + "__max")) name = terms.get('name') if name: area_query = area_query.filter(areaname__value__icontains=name) code = terms.get('classification') if code: area_query = area_query.filter(areacode__value=code) latitude = terms.get('latitude') longitude = terms.get('longitude') if latitude and longitude: try: latitude = float(latitude) longitude = float(longitude) except ValueError: latitude = 0 longitude = 0 point = geos.Point(latitude, longitude) radius = terms.get('radius') if radius: try: radius = float(radius) except ValueError: radius = 0 area_query = area_query.filter( areageometry__value__dwithin=(point, radius)) else: area_query = area_query.filter( areageometry__value__bbcontains=point) return area_query
class Violation(models.Model, BaseModel, SourcesMixin, VersionsMixin, GetComplexFieldNameMixin): uuid = models.UUIDField(default=uuid.uuid4, editable=False, db_index=True) published = models.BooleanField(default=False) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Dates and status self.startdate = ComplexFieldContainer(self, ViolationStartDate) self.first_allegation = ComplexFieldContainer( self, ViolationFirstAllegation) self.enddate = ComplexFieldContainer(self, ViolationEndDate) self.last_update = ComplexFieldContainer(self, ViolationLastUpdate) self.status = ComplexFieldContainer(self, ViolationStatus) # Location fields self.locationdescription = ComplexFieldContainer( self, ViolationLocationDescription) self.adminlevel1 = ComplexFieldContainer(self, ViolationAdminLevel1) self.adminlevel2 = ComplexFieldContainer(self, ViolationAdminLevel2) self.osmname = ComplexFieldContainer(self, ViolationOSMName) self.osmid = ComplexFieldContainer(self, ViolationOSMId) self.division_id = ComplexFieldContainer(self, ViolationDivisionId) self.location = ComplexFieldContainer(self, ViolationLocation) self.location_name = ComplexFieldContainer(self, ViolationLocationName) self.location_id = ComplexFieldContainer(self, ViolationLocationId) # Descriptions and other attributes self.description = ComplexFieldContainer(self, ViolationDescription) self.perpetrator = ComplexFieldListContainer(self, ViolationPerpetrator) self.perpetratororganization = ComplexFieldListContainer( self, ViolationPerpetratorOrganization) self.perpetratorclassification = ComplexFieldListContainer( self, ViolationPerpetratorClassification) self.types = ComplexFieldListContainer(self, ViolationType) self.complex_fields = [ self.startdate, self.first_allegation, self.enddate, self.last_update, self.status, self.locationdescription, self.adminlevel1, self.adminlevel2, self.location, self.description, self.division_id ] self.complex_lists = [ self.perpetrator, self.perpetratororganization, self.perpetratorclassification, self.types ] self.required_fields = [self.description, self.startdate, self.enddate] def get_value(self): return self.description.get_value() @property def related_entities(self): """ Return a list of dicts with metadata for all of the entities linked to this Violation. Metadata dicts must have the following keys: - name - entity_type - url (a link to edit the entity) """ related_entities = [] # Second-highest administrative level for the location of the violation. if self.adminlevel1.get_value(): location = self.adminlevel1.get_value().value related_entities.append({ 'name': location.name, 'entity_type': _('AdminLevel1'), 'url': reverse('edit-violation', args=[self.uuid]) }) # Highest administrative level for the location of the violation. if self.adminlevel2.get_value(): location = self.adminlevel2.get_value().value related_entities.append({ 'name': location.name, 'entity_type': _('AdminLevel2'), 'url': reverse('edit-violation', args=[self.uuid]) }) # The location of the violation. if self.location.get_value(): location = self.location.get_value().value related_entities.append({ 'name': location.name, 'entity_type': _('Location'), 'url': reverse('edit-violation', args=[self.uuid]) }) # The perpetrators of the violation (personnel). perpetrators = self.perpetrator.get_list() if perpetrators: perpetrators = [ perp.get_value() for perp in perpetrators if perp.get_value() ] for perpetrator in perpetrators: person = perpetrator.value related_entities.append({ 'name': person.name.get_value().value, 'entity_type': _('Perpetrator'), 'url': reverse('edit-violation', args=[self.uuid]) }) # The perpetrators of the violation (organizations). perpetratororganizations = self.perpetratororganization.get_list() if perpetratororganizations: perpetrators = [ perp.get_value() for perp in perpetratororganizations if perp.get_value() ] for perpetrator in perpetrators: org = perpetrator.value related_entities.append({ 'name': org.name.get_value().value, 'entity_type': _('PerpetratorOrganization'), 'url': reverse('edit-violation', args=[self.uuid]) }) return related_entities
class MembershipPerson(models.Model, BaseModel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.member = ComplexFieldContainer(self, MembershipPersonMember) self.organization = ComplexFieldContainer(self, MembershipPersonOrganization) self.role = ComplexFieldContainer(self, MembershipPersonRole) self.title = ComplexFieldContainer(self, MembershipPersonTitle) self.rank = ComplexFieldContainer(self, MembershipPersonRank) self.realstart = ComplexFieldContainer(self, MembershipPersonRealStart) self.realend = ComplexFieldContainer(self, MembershipPersonRealEnd) self.startcontext = ComplexFieldContainer(self, MembershipPersonStartContext) self.endcontext = ComplexFieldContainer(self, MembershipPersonEndContext) self.firstciteddate = ComplexFieldContainer(self, MembershipPersonFirstCitedDate) self.lastciteddate = ComplexFieldContainer(self, MembershipPersonLastCitedDate) self.complex_fields = [self.member, self.organization, self.role, self.title, self.rank, self.realstart, self.realend, self.startcontext, self.endcontext, self.firstciteddate, self.lastciteddate] self.complex_lists = [] self.required_fields = [ "MembershipPerson_MembershipPersonMember", "MembershipPerson_MembershipPersonOrganization", ] @property def short_description(self): ''' Get a description string (as HTML) for information on this membership, such as: "General Officer Commanding, Major General, Commander of 82 Division (Military/Army, Nigeria) on 1st January 2013" ''' obj = self # Start with the epithets (title, rank, and role) description = '<strong>' epithets = [obj.title.get_value(), obj.rank.get_value(), obj.role.get_value()] epithets = [str(ep.value) for ep in epithets if ep is not None] if len(epithets) == 1: description += epithets[0] + '</strong>' elif len(epithets) == 2 or len(epithets) == 3: separator = '</strong>, <strong>' description += separator.join(epithets) + '</strong>' else: # Length must be 0, so use a generic title description = _('Member') # Member organization description += ' ' organization = obj.organization.get_value().value href = reverse('view-organization', args=(organization.uuid,)) # Translators: This is part of the string "{Rank} of {unit}" joiner = _('of') org_string = joiner + ' <strong><a href="{href}">{org}</a></strong>' description += org_string.format(org=organization, href=href) # Classifications description += ' ' classifications = organization.classification.get_list() if classifications: classifications = '/'.join(str(clss) for clss in classifications if clss is not None) description += '(%s)' % classifications # Last cited date description += ' ' last_cited = obj.lastciteddate.get_value() if last_cited: # Translators: This is part of the "Last seen as" string for a person, # as in "last seen as {rank} of {unit} on {date}" date_joiner = _('on') date_string = date_joiner + ' <strong>%s</strong>' % last_cited description += date_string return description @classmethod def from_id(cls, id_): try: membership = cls.objects.get(id=id_) return membership except cls.DoesNotExist: return None def get_value(self): return '{0} member of {1}'.format(self.member.get_value(), self.organization.get_value()) @classmethod def create(cls, dict_values, lang=get_language()): membership = cls() membership.update(dict_values, lang) return membership
class Person(models.Model, BaseModel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.name = ComplexFieldContainer(self, PersonName) self.alias = ComplexFieldContainer(self, PersonAlias) self.deathdate = ComplexFieldContainer(self, PersonDeathDate) self.complex_fields = [self.name, self.alias, self.deathdate] self.required_fields = [ "Person_PersonName", ] def get_value(self): return self.name.get_value() def __str__(self): return str(self.name) @classmethod def search(cls, terms): order_by = terms.get('orderby') if not order_by: order_by = 'personname__value' elif order_by in ['name']: order_by = 'person' + order_by + '__value' direction = terms.get('direction') if not direction: direction = 'ASC' dirsym = '' if direction == 'DESC': dirsym = '-' person_query = (cls.objects.annotate( Max(order_by)).order_by(dirsym + order_by + "__max")) name = terms.get('name') if name: person_query = person_query.filter( personname__value__icontains=name) alias_val = terms.get('alias') if alias_val: person_query = person_query.filter( personalias__value__icontains=alias_val) deathdate_year = terms.get('deathdate_year') if deathdate_year: person_query = person_query.filter( persondeathdate__value__startswith=deathdate_year) deathdate_month = terms.get('deathdate_month') if deathdate_month: person_query = person_query.filter( persondeathdate__value__contains="-" + deathdate_month + "-") deathdate_day = terms.get('deathdate_day') if deathdate_day: person_query = person_query.filter( persondeathdate__value__endswith=deathdate_day) role = terms.get('role_membership') if role: person_query = person_query.filter( membershippersonmember__object_ref__membershiprole__value__value =role) latitude = terms.get('latitude') longitude = terms.get('longitude') if latitude and longitude: try: latitude = float(latitude) longitude = float(longitude) except ValueError: latitude = 0 longitude = 0 point = Point(latitude, longitude) radius = terms.get('radius') if radius: try: radius = float(radius) except ValueError: radius = 0 person_query = person_query.filter( membershippersonmember__object_ref__membershiporganization__value__associationorganization__object_ref__associationarea__value__areageometry__value__dwithin =(point, radius)) else: person_query = person_query.filter( membershippersonmember__object_ref__membershiporganization__value__associationorganization__object_ref__associationarea__value__areageometry__value__bbcontains =point) return person_query
class MembershipPerson(models.Model, BaseModel, SourcesMixin, GetComplexFieldNameMixin): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.member = ComplexFieldContainer(self, MembershipPersonMember) self.organization = ComplexFieldContainer(self, MembershipPersonOrganization) self.role = ComplexFieldContainer(self, MembershipPersonRole) self.title = ComplexFieldContainer(self, MembershipPersonTitle) self.rank = ComplexFieldContainer(self, MembershipPersonRank) self.realstart = ComplexFieldContainer(self, MembershipPersonRealStart) self.realend = ComplexFieldContainer(self, MembershipPersonRealEnd) self.startcontext = ComplexFieldContainer(self, MembershipPersonStartContext) self.endcontext = ComplexFieldContainer(self, MembershipPersonEndContext) self.firstciteddate = ComplexFieldContainer(self, MembershipPersonFirstCitedDate) self.lastciteddate = ComplexFieldContainer(self, MembershipPersonLastCitedDate) self.complex_fields = [self.member, self.organization, self.role, self.title, self.rank, self.realstart, self.realend, self.startcontext, self.endcontext, self.firstciteddate, self.lastciteddate] self.complex_lists = [] self.required_fields = [ "MembershipPerson_MembershipPersonMember", "MembershipPerson_MembershipPersonOrganization", ] @property def short_description(self): ''' Get a description string (as HTML) for information on this membership, such as: "General Officer Commanding, Major General, Commander of 82 Division (Military/Army, Nigeria) on 1st January 2013" ''' obj = self # Start with the epithets (title, rank, and role) description = '<strong>' epithets = [obj.title.get_value(), obj.rank.get_value(), obj.role.get_value()] epithets = [str(ep.value) for ep in epithets if ep is not None] if len(epithets) == 1: description += epithets[0] + '</strong>' elif len(epithets) == 2 or len(epithets) == 3: separator = '</strong>, <strong>' description += separator.join(epithets) + '</strong>' else: # Length must be 0, so use a generic title description = _('Member') # Member organization description += ' ' organization = obj.organization.get_value().value href = reverse('view-organization', args=(organization.uuid,)) # Translators: This is part of the string "{Rank} of {unit}" joiner = _('of') org_string = joiner + ' <strong><a href="{href}">{org}</a></strong>' description += org_string.format(org=organization, href=href) # Classifications description += ' ' classifications = organization.classification.get_list() if classifications: classifications = '/'.join(str(clss) for clss in classifications if clss is not None) description += '(%s)' % classifications # Last cited date description += ' ' last_cited = obj.lastciteddate.get_value() if last_cited: # Translators: This is part of the "Last seen as" string for a person, # as in "last seen as {rank} of {unit} on {date}" date_joiner = _('on') date_string = date_joiner + ' <strong>%s</strong>' % last_cited description += date_string return description @classmethod def from_id(cls, id_): try: membership = cls.objects.get(id=id_) return membership except cls.DoesNotExist: return None def get_value(self): return '{0} member of {1}'.format(self.member.get_value(), self.organization.get_value()) @classmethod def create(cls, dict_values, lang=get_language()): membership = cls() membership.update(dict_values, lang) return membership
class Organization(models.Model, BaseModel, VersionsMixin): uuid = models.UUIDField(default=uuid.uuid4, editable=False, db_index=True) published = models.BooleanField(default=False) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.name = ComplexFieldContainer(self, OrganizationName) self.aliases = ComplexFieldListContainer(self, OrganizationAlias) self.classification = ComplexFieldListContainer(self, OrganizationClassification) self.division_id = ComplexFieldContainer(self, OrganizationDivisionId) self.headquarters = ComplexFieldContainer(self, OrganizationHeadquarters) self.firstciteddate = ComplexFieldContainer(self, OrganizationFirstCitedDate) self.lastciteddate = ComplexFieldContainer(self, OrganizationLastCitedDate) self.realstart = ComplexFieldContainer(self, OrganizationRealStart) self.open_ended = ComplexFieldContainer(self, OrganizationOpenEnded) self.complex_fields = [self.name, self.division_id, self.firstciteddate, self.lastciteddate, self.realstart, self.open_ended, self.headquarters] self.complex_lists = [self.aliases, self.classification] self.required_fields = [ "Organization_OrganizationName", ] def get_value(self): return self.name.get_value() def __str__(self): return str(self.name) @property def associations(self): ''' Return all of this organization's associations, in a custom sorting order. Order by first cited date descending, then last cited date descending, with nulls last. ''' assocs = self.associationorganization_set\ .annotate(lcd=Coalesce('object_ref__associationstartdate__value', 'object_ref__associationenddate__value', models.Value('1000-0-0')))\ .order_by('-lcd') return assocs @property def emplacements(self): ''' Return all of this organization's emplacements, in a custom sorting order. Order by first cited date descending, then last cited date descending, with nulls last. ''' empls = self.emplacementorganization_set\ .annotate(lcd=Coalesce('object_ref__emplacementstartdate__value', 'object_ref__emplacementenddate__value', models.Value('1000-0-0')))\ .order_by('-lcd') return empls @property def personnel(self): ''' Returns all personnel ever assigned to a unit Objects returned are MembershipPerson objects ''' return [o.object_ref for o in self.membershippersonorganization_set.all()] @property def alias_list(self): return ', '.join(a.get_value().value for a in self.aliases.get_list())
class Geosite(models.Model, BaseModel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.name = ComplexFieldContainer(self, GeositeName) self.adminlevel1 = ComplexFieldContainer(self, GeositeAdminLevel1) self.adminlevel2 = ComplexFieldContainer(self, GeositeAdminLevel2) self.coordinates = ComplexFieldContainer(self, GeositeCoordinates) self.geoname = ComplexFieldContainer(self, GeositeGeoname) self.geonameid = ComplexFieldContainer(self, GeositeGeonameId) self.complex_fields = [ self.name, self.adminlevel1, self.adminlevel2, self.coordinates, self.geoname, self.geonameid ] self.required_fields = ["Geosite_GeositeName"] def get_value(self): return self.name.get_value() def __str__(self): return str(self.name) def validate(self, dict_values): errors = {} coordinates = dict_values['Geosite_GeositeCoordinates'].get("value") if coordinates: coord = json.loads(coordinates).get("coordinates") if coord: try: geos.Point(coord) except TypeError: errors["Geosite_GeositeCoordinates"] = ( "The coordinates must be a point, not a polygon") (base_errors, values) = super().validate(dict_values) errors.update(base_errors) return (errors, values) @classmethod def search(cls, terms): order_by = terms.get('orderby') if not order_by: order_by = 'geositename__value' elif order_by in ['name']: order_by = 'geosite' + order_by + '__value' direction = terms.get('direction') if not direction: direction = 'ASC' dirsym = '' if direction == 'DESC': dirsym = '-' geosite_query = (Geosite.objects.annotate( Max(order_by)).order_by(dirsym + order_by + "__max")) name = terms.get('name') if name: geosite_query = geosite_query.filter( geositename__value__icontains=name) admin1 = terms.get('adminlevel1') if admin1: geosite_query = geosite_query.filter( geositeadminlevel1__value__icontains=admin1) admin2 = terms.get('adminlevel2') if admin2: geosite_query = geosite_query.filter( geositeadminlevel2__value__icontains=admin2) latitude = terms.get('latitude') longitude = terms.get('longitude') if latitude and longitude: try: latitude = float(latitude) longitude = float(longitude) except ValueError: latitude = 0 longitude = 0 point = geos.Point(latitude, longitude) radius = terms.get('radius') if radius: try: radius = float(radius) except ValueError: radius = 0 geosite_query = geosite_query.filter( geositecoordinates__value__dwithin=(point, radius)) else: geosite_query = geosite_query.filter( geositecoordinates__value__bbcontains=point) geoname = terms.get('geoname') if geoname: geosite_query = geosite_query.filter( geositegeoname__value__icontains=geoname) geonameid = terms.get('geonameid') if geonameid: geosite_query = geosite_query.filter( geositegeonameid__value=geonameid) return geosite_query
class Organization(models.Model, BaseModel): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.name = ComplexFieldContainer(self, OrganizationName) self.alias = ComplexFieldContainer(self, OrganizationAlias) self.classification = ComplexFieldContainer( self, OrganizationClassification) self.foundingdate = ComplexFieldContainer(self, OrganizationFoundingDate) self.dissolutiondate = ComplexFieldContainer( self, OrganizationDissolutionDate) self.realfounding = ComplexFieldContainer(self, OrganizationRealFounding) self.realdissolution = ComplexFieldContainer( self, OrganizationRealDissolution) self.complex_fields = [ self.name, self.alias, self.classification, self.foundingdate, self.dissolutiondate, self.realfounding, self.realdissolution ] self.required_fields = [ "Organization_OrganizationName", ] def get_value(self): return self.name.get_value() def __str__(self): return str(self.name) @classmethod def search(cls, terms): order_by = terms.get('orderby') if not order_by: order_by = 'organizationname__value' direction = terms.get('direction') if not direction: direction = 'ASC' dirsym = '' if direction == 'DESC': dirsym = '-' orgs_query = (Organization.objects.annotate( Max(order_by)).order_by(dirsym + order_by + "__max")) name = terms.get('name') if name: orgs_query = orgs_query.filter( organizationname__value__icontains=name) alias_val = terms.get('alias') if alias_val: orgs_query = orgs_query.filter( organizationalias__value__icontains=alias_val) foundingdate_year = terms.get('founding_year') if foundingdate_year: orgs_query = orgs_query.filter( organizationfoundingdate__value__startswith=foundingdate_year) foundingdate_month = terms.get('founding_month') if foundingdate_month: orgs_query = orgs_query.filter( organizationfoundingdate__value__contains="-" + foundingdate_month + "-") foundingdate_day = terms.get('founding_day') if foundingdate_day: orgs_query = orgs_query.filter( organizationfoundingdate__value__endswith=foundingdate_day) dissolutiondate_year = terms.get('dissolution_year') if dissolutiondate_year: orgs_query = orgs_query.filter( organizationdissolutiondate__value__startswith= dissolutiondate_year) dissolutiondate_month = terms.get('dissolution_month') if dissolutiondate_month: orgs_query = orgs_query.filter( organizationdissolutiondate__value__contains="-" + dissolutiondate_month + "-") dissolutiondate_day = terms.get('dissolution_day') if dissolutiondate_day: orgs_query = orgs_query.filter( organizationdissolutiondate__value__endswith=dissolutiondate_day ) classification = terms.get('classification') if classification: orgs_query = orgs_query.filter( organizationclassification__value_id=classification) latitude = terms.get('latitude') longitude = terms.get('longitude') if latitude and longitude: try: latitude = float(latitude) longitude = float(longitude) except ValueError: latitude = 0 longitude = 0 point = geos.Point(latitude, longitude) radius = terms.get('radius') if radius: try: radius = float(radius) except ValueError: radius = 0 orgs_query = orgs_query.filter( associationorganization__object_ref__associationarea__value__areageometry__value__dwithin =(point, radius)) else: orgs_query = orgs_query.filter( associationorganization__object_ref__associationarea__value__areageometry__value__bbcontains =point) return orgs_query
class Organization(models.Model, BaseModel, SourcesMixin, VersionsMixin, GetComplexFieldNameMixin): uuid = models.UUIDField(default=uuid.uuid4, editable=False, db_index=True) published = models.BooleanField(default=False) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.name = ComplexFieldContainer(self, OrganizationName) self.aliases = ComplexFieldListContainer(self, OrganizationAlias) self.classification = ComplexFieldListContainer(self, OrganizationClassification) self.division_id = ComplexFieldContainer(self, OrganizationDivisionId) self.headquarters = ComplexFieldContainer(self, OrganizationHeadquarters) self.firstciteddate = ComplexFieldContainer(self, OrganizationFirstCitedDate) self.lastciteddate = ComplexFieldContainer(self, OrganizationLastCitedDate) self.realstart = ComplexFieldContainer(self, OrganizationRealStart) self.open_ended = ComplexFieldContainer(self, OrganizationOpenEnded) self.complex_fields = [self.name, self.division_id, self.firstciteddate, self.lastciteddate, self.realstart, self.open_ended, self.headquarters] self.complex_lists = [self.aliases, self.classification] self.required_fields = [ "Organization_OrganizationName", ] def get_value(self): return self.name.get_value() def __str__(self): return str(self.name) @property def associations(self): ''' Return all of this organization's associations, in a custom sorting order. Order by first cited date descending, then last cited date descending, with nulls last. ''' from association.models import AssociationTenure return AssociationTenure.objects\ .filter(association__associationorganization__value=self)\ .select_related('association', 'startdate', 'enddate')\ .order_by( F('startdate__value').desc(nulls_last=True), F('enddate__value').desc(nulls_last=True), 'association__associationarea__value', ) @property def emplacements(self): ''' Return all of this organization's emplacements, in a custom sorting order. Order by first cited date descending, then last cited date descending, with nulls last. ''' from emplacement.models import EmplacementTenure return EmplacementTenure.objects\ .filter(emplacement__emplacementorganization__value=self)\ .select_related('emplacement', 'startdate', 'enddate')\ .order_by( F('startdate__value').desc(nulls_last=True), F('enddate__value').desc(nulls_last=True), 'emplacement__emplacementsite__value', ) @property def personnel(self): ''' Returns all personnel ever assigned to a unit Objects returned are MembershipPerson objects ''' return [o.object_ref for o in self.membershippersonorganization_set.all()] @property def alias_list(self): return ', '.join(a.get_value().value for a in self.aliases.get_list()) @property def related_entities(self): """ Return a list of dicts with metadata for all of the entities linked to this Organization. Metadata dicts must have the following keys: - name - entity_type - start_date - end_date - open_ended - url (a link to edit the entity) """ related_entities = [] # People that are posted to this organization. for membershipperson in self.membershippersonorganization_set.all(): membership = membershipperson.object_ref person = membership.member.get_value().value related_entities.append({ 'name': person.name.get_value().value, 'entity_type': _('MembershipPerson'), 'start_date': membership.firstciteddate.get_value(), 'end_date': membership.lastciteddate.get_value(), 'open_ended': membership.realend.get_value(), 'url': reverse( 'edit-organization-personnel', kwargs={ 'organization_id': self.uuid, 'pk': membership.pk } ), }) # Organizations that are children of this org. for compositionparent in self.child_organization.all(): composition = compositionparent.object_ref child = composition.child.get_value().value related_entities.append({ 'name': child.name.get_value().value, 'entity_type': _('Composition'), 'start_date': composition.startdate.get_value(), 'end_date': composition.enddate.get_value(), 'open_ended': composition.open_ended.get_value(), 'url': reverse( 'edit-organization-composition', kwargs={ 'organization_id': self.uuid, 'pk': composition.pk } ), }) # Organizations that are parents of this org. for compositionchild in self.parent_organization.all(): composition = compositionchild.object_ref parent = composition.parent.get_value().value related_entities.append({ 'name': parent.name.get_value().value, 'entity_type': _('Composition'), 'start_date': composition.startdate.get_value(), 'end_date': composition.enddate.get_value(), 'open_ended': composition.open_ended.get_value(), 'url': reverse( 'edit-organization-composition', kwargs={ 'organization_id': self.uuid, 'pk': composition.pk } ), }) # Organizations that this org is a member of. for membershiporganizationmember in self.membershiporganizationmember_set.all(): membership = membershiporganizationmember.object_ref member_org = membership.organization.get_value().value related_entities.append({ 'name': member_org.name.get_value().value, 'entity_type': _('MembershipOrganization'), 'start_date': membership.firstciteddate.get_value(), 'end_date': membership.lastciteddate.get_value(), 'open_ended': membership.open_ended.get_value(), 'url': reverse( 'edit-organization-membership', kwargs={ 'organization_id': self.uuid, 'pk': membership.pk } ), }) # Organizations that are members of this org. for membershiporganizationorganization in self.membershiporganizationorganization_set.all(): membership = membershiporganizationorganization.object_ref member_org = membership.member.get_value().value related_entities.append({ 'name': member_org.name.get_value().value, 'entity_type': _('MembershipOrganization'), 'start_date': membership.firstciteddate.get_value(), 'end_date': membership.lastciteddate.get_value(), 'open_ended': membership.open_ended.get_value(), 'url': reverse( 'edit-organization-membership', kwargs={ 'organization_id': self.uuid, 'pk': membership.pk } ), }) # Areas of operation. for associationorganization in self.associationorganization_set.all(): association = associationorganization.object_ref location = association.area.get_value().value related_entities.append({ 'name': location.name, 'entity_type': _('Association'), 'start_date': association.startdate.get_value(), 'end_date': association.enddate.get_value(), 'open_ended': association.open_ended.get_value(), 'url': reverse( 'edit-organization-association', kwargs={ 'organization_id': self.uuid, 'pk': association.pk } ), }) # Organization sites. for emplacementorganization in self.emplacementorganization_set.all(): emplacement = emplacementorganization.object_ref location = emplacement.site.get_value().value related_entities.append({ 'name': location.name, 'entity_type': _('Emplacement'), 'start_date': emplacement.startdate.get_value(), 'end_date': emplacement.enddate.get_value(), 'open_ended': emplacement.open_ended.get_value(), 'url': reverse( 'edit-organization-emplacement', kwargs={ 'organization_id': self.uuid, 'pk': emplacement.pk } ), }) # Violations where this org was a perpetrator. for violationperpetrator in self.violationperpetratororganization_set.all(): violation = violationperpetrator.object_ref related_entities.append({ 'name': truncatewords(violation.description.get_value(), 10), 'entity_type': _('Violation'), 'start_date': violation.startdate.get_value(), 'end_date': violation.enddate.get_value(), 'open_ended': '', 'url': reverse('edit-violation', kwargs={'slug': violation.uuid}), }) return related_entities
class Person(models.Model, BaseModel, SourcesMixin, VersionsMixin, GetComplexFieldNameMixin): uuid = models.UUIDField(default=uuid.uuid4, editable=False, db_index=True) published = models.BooleanField(default=False) def __init__(self, *args, **kwargs): self.name = ComplexFieldContainer(self, PersonName) self.aliases = ComplexFieldListContainer(self, PersonAlias) self.division_id = ComplexFieldContainer(self, PersonDivisionId) self.notes = ComplexFieldContainer(self, PersonNotes) self.complex_fields = [ self.name, self.division_id, self.notes, ] self.complex_lists = [self.aliases] self.required_fields = [ "Person_PersonName", ] super().__init__(*args, **kwargs) def get_value(self): return self.name.get_value() def __str__(self): try: return str(self.personname_set.first().value) except AttributeError: return str(self.uuid) def get_absolute_url(self): return reverse('view-person', kwargs={'slug': self.uuid}) @cached_property def memberships(self): ''' Return all of this person's memberships, in a custom sorting order. Order by first cited date descending, then last cited date descending, with nulls last. ''' mems = self.membershippersonmember_set\ .select_related('object_ref')\ .annotate(lcd=Coalesce('object_ref__membershippersonfirstciteddate__value', 'object_ref__membershippersonlastciteddate__value', models.Value('1000-0-0')))\ .order_by('-lcd') return mems @property def last_cited(self): ''' Get the global last citation date for this person, leaving out nulls. ''' order = '-object_ref__membershippersonlastciteddate__value' memberships = self.membershippersonmember_set.order_by(order) for membership in memberships: # Filter nulls lcd = membership.object_ref.lastciteddate.get_value() if lcd: return lcd @property def first_cited(self): ''' Get the global first citation date for this person, leaving out nulls. ''' order = 'object_ref__membershippersonfirstciteddate__value' memberships = self.membershippersonmember_set.order_by(order) for membership in memberships: fcd = membership.object_ref.firstciteddate.get_value() if fcd: return fcd @property def related_entities(self): """ Return a list of dicts with metadata for all of the entities linked to this Person. Metadata dicts must have the following keys: - name - entity_type - start_date - end_date - open_ended - url (a link to edit the entity) """ related_entities = [] # This person's postings. for membershippersonmember in self.membershippersonmember_set.all(): membership = membershippersonmember.object_ref organization = membership.organization.get_value().value related_entities.append({ 'name': organization.name.get_value().value, 'entity_type': _('MembershipPerson'), 'start_date': membership.firstciteddate.get_value(), 'end_date': membership.lastciteddate.get_value(), 'open_ended': membership.realend.get_value(), 'url': reverse( 'edit-person-postings', kwargs={ 'person_id': self.uuid, 'pk': membership.pk } ), }) # Incidents where this person was a perpetrator. for violationperpetrator in self.violationperpetrator_set.all(): violation = violationperpetrator.object_ref related_entities.append({ 'name': truncatewords(violation.description.get_value(), 10), 'entity_type': _('Violation'), 'start_date': violation.startdate.get_value(), 'end_date': violation.enddate.get_value(), 'open_ended': '', 'url': reverse('edit-violation', kwargs={'slug': violation.uuid}), }) return related_entities