Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apis_v1/documentation_source/all_ballot_items_retrieve_doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ def all_ballot_items_retrieve_doc_template_values(url_root):
' "measure_text": string (if kind_of_ballot_item is MEASURE)\n' \
' "measure_url": string (if kind_of_ballot_item is MEASURE)\n' \
' "no_vote_description": string (if kind_of_ballot_item is MEASURE)\n' \
' "referendum_con": string (if kind_of_ballot_item is MEASURE)\n' \
' "referendum_pro": string (if kind_of_ballot_item is MEASURE)\n' \
' "state_code": string,\n' \
' "yes_vote_description": string (if kind_of_ballot_item is MEASURE)\n' \
' ],\n' \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ def ballot_item_options_retrieve_doc_template_values(url_root):
' "measure_url": string,\n' \
' "measure_we_vote_id": string,\n' \
' "no_vote_description": string,\n' \
' "referendum_con": string,\n' \
' "referendum_pro": string,\n' \
' "state_code": string,\n' \
' "yes_vote_description": string,\n' \
' ],\n' \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ def ballot_items_search_retrieve_doc_template_values(url_root):
' "measure_text": string (if kind_of_ballot_item is MEASURE)\n' \
' "measure_url": string (if kind_of_ballot_item is MEASURE)\n' \
' "no_vote_description": string (if kind_of_ballot_item is MEASURE)\n' \
' "referendum_con": string (if kind_of_ballot_item is MEASURE)\n' \
' "referendum_pro": string (if kind_of_ballot_item is MEASURE)\n' \
' "state_code": string,\n' \
' "yes_vote_description": string (if kind_of_ballot_item is MEASURE)\n' \
' ],\n' \
Expand Down
2 changes: 2 additions & 0 deletions apis_v1/documentation_source/ballot_items_sync_out_doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def ballot_items_sync_out_doc_template_values(url_root):
' "measure_url": string,\n' \
' "no_vote_description": string,\n' \
' "polling_location_we_vote_id": string,\n' \
' "referendum_con": string,\n' \
' "referendum_pro": string,\n' \
' "yes_vote_description": string,\n' \
'}]'

Expand Down
2 changes: 2 additions & 0 deletions apis_v1/documentation_source/measure_retrieve_doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ def measure_retrieve_doc_template_values(url_root):
' "measure_url": string,\n' \
' "no_vote_description": string,\n' \
' "ocd_division_id": string,\n' \
' "referendum_con": string,\n' \
' "referendum_pro": string,\n' \
' "regional_display_name": string,\n' \
' "state_code": string,\n' \
' "state_display_name": string,\n' \
Expand Down
2 changes: 2 additions & 0 deletions apis_v1/documentation_source/measures_sync_out_doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ def measures_sync_out_doc_template_values(url_root):
' "measure_url": string,\n' \
' "ocd_division_id": string,\n' \
' "primary_party": string,\n' \
' "referendum_con": string,\n' \
' "referendum_pro": string,\n' \
' "state_code": string,\n' \
' "wikipedia_page_id": string,\n' \
' "wikipedia_page_title": string,\n' \
Expand Down
10 changes: 10 additions & 0 deletions ballot/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2564,6 +2564,8 @@ def all_ballot_items_retrieve_for_one_election_for_api(google_civic_election_id,
'no_vote_description': strip_html_tags(contest_measure.ballotpedia_no_vote_description),
# 'district_name': "", # TODO Add this
'election_display_name': election_name,
'referendum_con': strip_html_tags(contest_measure.referendum_con),
'referendum_pro': strip_html_tags(contest_measure.referendum_pro),
# 'regional_display_name': "", # TODO Add this
# 'state_display_name': "", # TODO Add this
'we_vote_id': measure_we_vote_id,
Expand Down Expand Up @@ -3087,6 +3089,8 @@ def generate_ballot_item_list_from_object_list(
measure_text = measure_results_dict[measure_we_vote_id].measure_text
measure_url = measure_results_dict[measure_we_vote_id].measure_url
no_vote_description = measure_results_dict[measure_we_vote_id].ballotpedia_no_vote_description
referendum_con = measure_results_dict[measure_we_vote_id].referendum_con
referendum_pro = measure_results_dict[measure_we_vote_id].referendum_pro
state_code = measure_results_dict[measure_we_vote_id].state_code
yes_vote_description = measure_results_dict[measure_we_vote_id].ballotpedia_yes_vote_description
else:
Expand All @@ -3095,6 +3099,8 @@ def generate_ballot_item_list_from_object_list(
measure_text = ballot_item.measure_text
measure_url = ballot_item.measure_url
no_vote_description = ballot_item.no_vote_description
referendum_con = ballot_item.referendum_con
referendum_pro = ballot_item.referendum_pro
state_code = ballot_item.state_code
yes_vote_description = ballot_item.yes_vote_description
except Exception as e:
Expand All @@ -3104,6 +3110,8 @@ def generate_ballot_item_list_from_object_list(
measure_text = ballot_item.measure_text
measure_url = ballot_item.measure_url
no_vote_description = ballot_item.no_vote_description
referendum_con = ''
referendum_pro = ''
state_code = ballot_item.state_code
yes_vote_description = ballot_item.yes_vote_description
one_ballot_item = {
Expand All @@ -3120,6 +3128,8 @@ def generate_ballot_item_list_from_object_list(
'district_name': "", # TODO Add this
'election_display_name': "", # TODO Add this
'regional_display_name': "", # TODO Add this
'referendum_con': strip_html_tags(referendum_con),
'referendum_pro': strip_html_tags(referendum_pro),
'state_code': state_code,
'state_display_name': "", # TODO Add this
'we_vote_id': measure_we_vote_id,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 5.2.16 on 2026-09-12 17:04

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('ballot', '0008_ballotitem_election_state_index'),
]

operations = [
migrations.AddField(
model_name='ballotitem',
name='referendum_con',
field=models.TextField(blank=True, default=None),
),
migrations.AddField(
model_name='ballotitem',
name='referendum_pro',
field=models.TextField(blank=True, default=None),
),
]
23 changes: 23 additions & 0 deletions ballot/migrations/0010_alter_ballotitem_referendum_con_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 5.2.16 on 2026-09-14 17:29

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('ballot', '0009_ballotitem_referendum_con_ballotitem_referendum_pro'),
]

operations = [
migrations.AlterField(
model_name='ballotitem',
name='referendum_con',
field=models.TextField(blank=True, default='', null=True),
),
migrations.AlterField(
model_name='ballotitem',
name='referendum_pro',
field=models.TextField(blank=True, default='', null=True),
),
]
26 changes: 24 additions & 2 deletions ballot/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
function = 'ACOS'


class BallotItem(models.Model):

Check failure on line 58 in ballot/models.py

View workflow job for this annotation

GitHub Actions / Ruff

ruff (django-model-without-dunder-str)

ballot/models.py:58:7: django-model-without-dunder-str: Model does not define `__str__` method
"""
This is a generated table with ballot item data from a variety of sources, including Google Civic
One ballot item is either 1) a measure/referendum or 2) an office that is being competed for
Expand All @@ -64,17 +64,17 @@
voter_id = models.IntegerField(verbose_name="the voter unique id",
default=0, null=False, blank=False, db_index=True)
# The map point for which this ballot was retrieved
polling_location_we_vote_id = models.CharField(
verbose_name="we vote permanent id of the map point", max_length=255, default=None, null=True,
blank=True, unique=False, db_index=True)

Check failure on line 69 in ballot/models.py

View workflow job for this annotation

GitHub Actions / Ruff

ruff (django-nullable-model-string-field)

ballot/models.py:67:35: django-nullable-model-string-field: Avoid using `null=True` on string-based fields such as `CharField`

# The unique ID of this election. (Provided by Google Civic)
google_civic_election_id = models.CharField(verbose_name="google civic election id",
max_length=20, null=False, db_index=True)
google_civic_election_id_new = models.PositiveIntegerField(
verbose_name="google civic election id", default=0, null=False)
state_code = models.CharField(
verbose_name="state the ballot item is related to", max_length=2, null=True, db_index=True)

Check failure on line 77 in ballot/models.py

View workflow job for this annotation

GitHub Actions / Ruff

ruff (django-nullable-model-string-field)

ballot/models.py:76:18: django-nullable-model-string-field: Avoid using `null=True` on string-based fields such as `CharField`

google_ballot_placement = models.BigIntegerField(
verbose_name="the order this item should appear on the ballot", null=True, blank=True, unique=False)
Expand All @@ -83,30 +83,32 @@

# The id for this contest office specific to this server.
# TODO contest_office_id should be positive integer as opposed to CharField
contest_office_id = models.CharField(verbose_name="local id for this contest office", max_length=255, null=True,
blank=True)

Check failure on line 87 in ballot/models.py

View workflow job for this annotation

GitHub Actions / Ruff

ruff (django-nullable-model-string-field)

ballot/models.py:86:25: django-nullable-model-string-field: Avoid using `null=True` on string-based fields such as `CharField`
# The internal We Vote id for the ContestMeasure that this campaign taking a stance on
contest_office_we_vote_id = models.CharField(
verbose_name="we vote permanent id for this office", max_length=255, default=None, null=True,
blank=True, unique=False, db_index=True)

Check failure on line 91 in ballot/models.py

View workflow job for this annotation

GitHub Actions / Ruff

ruff (django-nullable-model-string-field)

ballot/models.py:89:33: django-nullable-model-string-field: Avoid using `null=True` on string-based fields such as `CharField`
# The local database id for this measure, specific to this server.
# TODO contest_measure_id should be positive integer as opposed to CharField
contest_measure_id = models.CharField(
verbose_name="contest_measure unique id", max_length=255, null=True, blank=True)

Check failure on line 95 in ballot/models.py

View workflow job for this annotation

GitHub Actions / Ruff

ruff (django-nullable-model-string-field)

ballot/models.py:94:26: django-nullable-model-string-field: Avoid using `null=True` on string-based fields such as `CharField`
# The internal We Vote id for the ContestMeasure that this campaign taking a stance on
contest_measure_we_vote_id = models.CharField(
verbose_name="we vote permanent id for this measure", max_length=255, default=None, null=True,
blank=True, unique=False, db_index=True)

Check failure on line 99 in ballot/models.py

View workflow job for this annotation

GitHub Actions / Ruff

ruff (django-nullable-model-string-field)

ballot/models.py:97:34: django-nullable-model-string-field: Avoid using `null=True` on string-based fields such as `CharField`
# This is a sortable name, either the candidate name or the measure name
ballot_item_display_name = models.CharField(verbose_name="a label we can sort by", max_length=255, null=True,
blank=True)

Check failure on line 102 in ballot/models.py

View workflow job for this annotation

GitHub Actions / Ruff

ruff (django-nullable-model-string-field)

ballot/models.py:101:32: django-nullable-model-string-field: Avoid using `null=True` on string-based fields such as `CharField`

measure_subtitle = models.TextField(verbose_name="google civic referendum subtitle",
null=True, blank=True, default="")

Check failure on line 105 in ballot/models.py

View workflow job for this annotation

GitHub Actions / Ruff

ruff (django-nullable-model-string-field)

ballot/models.py:104:24: django-nullable-model-string-field: Avoid using `null=True` on string-based fields such as `TextField`
measure_text = models.TextField(verbose_name="measure text", null=True, blank=True, default="")

Check failure on line 106 in ballot/models.py

View workflow job for this annotation

GitHub Actions / Ruff

ruff (django-nullable-model-string-field)

ballot/models.py:106:20: django-nullable-model-string-field: Avoid using `null=True` on string-based fields such as `TextField`
measure_url = models.TextField(verbose_name='url of measure', null=True)
yes_vote_description = models.TextField(verbose_name="what a yes vote means", null=True, blank=True, default=None)
no_vote_description = models.TextField(verbose_name="what a no vote means", null=True, blank=True, default=None)
referendum_con = models.TextField(blank=True, default="", null=True)
referendum_pro = models.TextField(blank=True, default="", null=True)

class Meta:
indexes = [
Expand Down Expand Up @@ -235,6 +237,8 @@
ballot_item.measure_text = contest_measure.measure_text
ballot_item.measure_url = contest_measure.measure_url
ballot_item.no_vote_description = contest_measure.ballotpedia_no_vote_description
ballot_item.referendum_con = contest_measure.referendum_con
ballot_item.referendum_pro = contest_measure.referendum_pro
ballot_item.yes_vote_description = contest_measure.ballotpedia_yes_vote_description
values_changed = True

Expand Down Expand Up @@ -388,6 +392,10 @@
create_values['yes_vote_description'] = defaults['yes_vote_description']
if 'no_vote_description' in defaults:
create_values['no_vote_description'] = defaults['no_vote_description']
if 'referendum_con' in defaults:
create_values['referendum_con'] = defaults['referendum_con']
if 'referendum_pro' in defaults:
create_values['referendum_pro'] = defaults['referendum_pro']

# We search with contest_measure_id and contest_office_id because they are (will be) integers,
# which will be a faster search
Expand Down Expand Up @@ -444,6 +452,12 @@
if 'no_vote_description' in defaults:
no_vote_description = defaults['no_vote_description']
ballot_item_on_stage.no_vote_description = no_vote_description
if 'referendum_con' in defaults:
referendum_con = defaults['referendum_con']
ballot_item_on_stage.referendum_con = referendum_con
if 'referendum_pro' in defaults:
referendum_pro = defaults['referendum_pro']
ballot_item_on_stage.referendum_pro = referendum_pro
ballot_item_on_stage.save()

success = True
Expand Down Expand Up @@ -683,6 +697,10 @@
if 'no_vote_description' in defaults:
no_vote_description = defaults['no_vote_description']
new_ballot_item.no_vote_description = no_vote_description
if 'referendum_con' in defaults:
new_ballot_item.referendum_con = defaults['referendum_con']
if 'referendum_pro' in defaults:
new_ballot_item.referendum_pro = defaults['referendum_pro']
if 'state_code' in defaults and positive_value_exists(defaults['state_code']):
state_code_from_defaults = defaults['state_code']
state_code_from_defaults = state_code_from_defaults.lower()
Expand All @@ -695,7 +713,7 @@
except Exception as e:
success = False
new_ballot_item_created = False
status += "BALLOT_ITEM_RETRIEVE_ERROR " + str(e) + " "
status += "CREATE-BALLOT_ITEM_RETRIEVE_ERROR: " + str(e) + " "
handle_exception(e, logger=logger, exception_message=status)

results = {
Expand Down Expand Up @@ -758,6 +776,8 @@
measure_text=contest_measure.measure_text,
measure_url=contest_measure.measure_url,
no_vote_description=contest_measure.ballotpedia_no_vote_description,
referendum_con=contest_measure.referendum_con,
referendum_pro=contest_measure.referendum_pro,
# state_code=contest_measure.state_code,
yes_vote_description=contest_measure.ballotpedia_yes_vote_description,
)
Expand Down Expand Up @@ -956,7 +976,7 @@
except Exception as e:
success = False
ballot_item_updated = False
status += "BALLOT_ITEM_RETRIEVE_ERROR: " + str(e) + " "
status += "UPDATE-BALLOT_ITEM_RETRIEVE_ERROR: " + str(e) + " "
handle_exception(e, logger=logger, exception_message=status)

results = {
Expand Down Expand Up @@ -1633,6 +1653,8 @@
defaults['measure_url'] = measure.get_measure_url()
defaults['yes_vote_description'] = measure.ballotpedia_yes_vote_description
defaults['no_vote_description'] = measure.ballotpedia_no_vote_description
defaults['referendum_con'] = measure.referendum_con
defaults['referendum_pro'] = measure.referendum_pro
google_ballot_placement = measure.google_ballot_placement
ballot_item_display_name = measure.measure_title
measure_subtitle = measure.measure_subtitle
Expand Down
Loading
Loading