class VoteEvent(OCDBase): id = OCDIDField(ocd_type='vote') identifier = models.CharField(max_length=300, blank=True) motion_text = models.TextField() # enum motion_classification = ArrayField(base_field=models.TextField(), blank=True, default=list) start_date = models.CharField(max_length=25) # YYYY-MM-DD HH:MM:SS+HH:MM end_date = models.CharField(max_length=25, blank=True) # YYYY-MM-DD HH:MM:SS+HH:MM result = models.CharField(max_length=50, choices=common.VOTE_RESULT_CHOICES) organization = models.ForeignKey(Organization, related_name='votes') legislative_session = models.ForeignKey(LegislativeSession, related_name='votes') bill = models.ForeignKey(Bill, related_name='votes', null=True) bill_action = models.OneToOneField(BillAction, related_name='vote', null=True, default=None) def __str__(self): if self.identifier: return '{} in {}'.format(self.identifier, self.legislative_session) else: return '{} on {}'.format(self.motion_text, self.bill) class Meta: db_table = 'opencivicdata_voteevent' index_together = [['legislative_session', 'identifier', 'bill'], ['legislative_session', 'bill']]
class Event(OCDBase): id = OCDIDField(ocd_type='event') name = models.CharField(max_length=1000) jurisdiction = models.ForeignKey( Jurisdiction, related_name='events', # jurisdictions hard to delete on_delete=models.PROTECT, ) description = models.TextField() classification = models.CharField(max_length=100) start_date = models.CharField(max_length=25) # YYYY-MM-DD HH:MM:SS+HH:MM end_date = models.CharField(max_length=25, blank=True) # YYYY-MM-DD HH:MM:SS+HH:MM all_day = models.BooleanField(default=False) status = models.CharField(max_length=20, choices=EVENT_STATUS_CHOICES) location = models.ForeignKey(EventLocation, null=True, on_delete=models.SET_NULL) def __str__(self): return '{0} ({1})'.format(self.name, self.start_date) class Meta: db_table = 'opencivicdata_event' index_together = [['jurisdiction', 'start_date', 'name']]
class Bill(OCDBase): id = OCDIDField(ocd_type='bill') legislative_session = models.ForeignKey( LegislativeSession, related_name='bills', # sessions should be hard to delete on_delete=models.PROTECT, ) identifier = models.CharField(max_length=100) title = models.TextField() from_organization = models.ForeignKey( Organization, related_name='bills', null=True, # chambers should be hard to delete on_delete=models.PROTECT, ) # check that array values are in enum? classification = ArrayField(base_field=models.TextField(), blank=True, default=list) subject = ArrayField(base_field=models.TextField(), blank=True, default=list) def __str__(self): return '{} in {}'.format(self.identifier, self.legislative_session) class Meta: db_table = 'opencivicdata_bill' index_together = [ ['from_organization', 'legislative_session', 'identifier'], ]
class VoteEvent(OCDBase): id = OCDIDField(ocd_type='vote') identifier = models.CharField(max_length=300, blank=True) motion_text = models.TextField() # enum motion_classification = ArrayField(base_field=models.TextField(), blank=True, default=list) start_date = models.CharField(max_length=25) # YYYY-MM-DD HH:MM:SS+HH:MM end_date = models.CharField(max_length=25, blank=True) # YYYY-MM-DD HH:MM:SS+HH:MM result = models.CharField(max_length=50, choices=common.VOTE_RESULT_CHOICES) organization = models.ForeignKey( Organization, related_name='votes', # make parent org hard to protect on_delete=models.PROTECT, ) legislative_session = models.ForeignKey( LegislativeSession, related_name='votes', # make legislative session hard to delete on_delete=models.PROTECT, ) bill = models.ForeignKey( Bill, related_name='votes', null=True, # if a bill was linked, the vote isn't meaningful without it on_delete=models.CASCADE, ) bill_action = models.OneToOneField( BillAction, related_name='vote', null=True, default=None, # if an action goes away - VoteEvent should stay on_delete=models.SET_NULL, ) extras = JSONField(default=dict, blank=True) def __str__(self): if self.identifier: return '{} in {}'.format(self.identifier, self.legislative_session) else: return '{} on {}'.format(self.motion_text, self.bill) class Meta: db_table = 'opencivicdata_voteevent' index_together = [['legislative_session', 'identifier', 'bill'], ['legislative_session', 'bill']]
class ContestBase(OCDBase): """ A base class for representing a specific decision set before voters in an election. Includes properties shared by all contest types: BallotMeasureContest, CandidateContest, PartyContest and RetentionContest. """ id = OCDIDField( ocd_type="contest", help_text= "Open Civic Data-style id in the format ``ocd-contest/{{uuid}}``.", ) name = models.CharField( max_length=300, help_text= "Name of the contest, not necessarily as it appears on the ballot.", ) division = models.ForeignKey( Division, related_name="%(class)ss", related_query_name="%(class)ss", help_text="Reference to the Division that defines the political " "geography of the contest, e.g., a specific Congressional or " "State Senate district. Should be a subdivision of the Division " "referenced by the contest's Election.", on_delete=models.PROTECT, ) election = models.ForeignKey( Election, related_name="%(class)ss", related_query_name="%(class)ss", help_text="Reference to the Election in which the contest is decided.", on_delete=models.CASCADE, ) def __str__(self): return "{0} (in {1})".format(self.name, self.election.name) class Meta: """ Model options. """ ordering = ( "election", "name", ) abstract = True
class Election(OCDBase): """ A collection of political contests set to be decided on the same date within a Division. """ id = OCDIDField( ocd_type="election", help_text= "Open Civic Data-style id in the format ``ocd-election/{{uuid}}``.", ) name = models.CharField(max_length=300, help_text="Name of the Election.") date = models.DateField( help_text="Final or only date when eligible voters may cast their " "ballots in the Election. Typically this is also the same " "date when results of the election's contests are first " "publicly reported.") division = models.ForeignKey( Division, related_name="elections", help_text= "Reference to the Division that defines the broadest political " "geography of any contest to be decided by the election.", # divisions should be tough to delete on_delete=models.PROTECT, ) administrative_organization = models.ForeignKey( Organization, related_name="elections", null=True, help_text= "Reference to the Organization that administers the election.", # shouldn't destroy election if org does go away on_delete=models.SET_NULL, ) def __str__(self): return "{0} ({1:%Y-%m-%d})".format(self.name, self.date) class Meta: """ Model options. """ db_table = "opencivicdata_election" ordering = ("-date", )
class Candidacy(OCDBase): """ A person seeking election to hold a specific public office for a term. """ id = OCDIDField( ocd_type='candidacy', help_text= 'Open Civic Data-style id in the format ``ocd-candidacy/{{uuid}}``.', ) person = models.ForeignKey( Person, related_name='candidacies', help_text='Reference to the Person who is the candidate.', ) post = models.ForeignKey( Post, related_name='candidacies', help_text='Reference to Post representing the public office for which ' 'the candidate is seeking election.', ) contest = models.ForeignKey( 'elections.CandidateContest', related_name='candidacies', help_text= "Reference to an OCD CandidateContest representing the contest " "in which the candidate is competing.", ) candidate_name = models.CharField( max_length=300, help_text= "For preserving the candidate's name as it was of the candidacy.") filed_date = models.DateField( null=True, help_text="Specifies when the candidate filed for the contest.", ) is_incumbent = models.NullBooleanField( help_text="Indicates whether the candidate is seeking re-election to a " "public office he/she currently holds", ) party = models.ForeignKey( Organization, related_name='candidacies', limit_choices_to={'classification': 'party'}, null=True, help_text= "Reference to the Organization representing the political party " "that nominated the candidate or would nominate the candidate " "(as in the case of a partisan primary).", ) REGISTRATION_STATUSES = ( ('filed', 'Filed'), ('qualified', 'Qualified'), ('withdrawn', 'Withdrawn'), ('write-in', 'Write-in'), ) registration_status = models.CharField( max_length=10, choices=REGISTRATION_STATUSES, null=True, help_text='Registration status of the candidate.', ) top_ticket_candidacy = models.ForeignKey( 'self', related_name="ticket", null=True, help_text="If the candidate is running as part of ticket, e.g., a Vice " "Presidential candidate running with a Presidential candidate, " "reference to candidacy at the top of the ticket.") def __str__(self): return '{0.candidate_name} for {0.contest}'.format(self) class Meta: """ Model options. """ db_table = 'opencivicdata_candidacy' verbose_name_plural = "candidacies" ordering = ( "contest", "post", "person", ) @property def election(self): """ Election in which the person is a candidate. """ return self.contest.election