diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index ac5a5a5..0586b9b 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -28,7 +28,7 @@ jobs: strategy: matrix: python-version: ['3.9', '3.10', '3.11', '3.12'] - django-series: ['3.2', '4.0', '4.2'] + django-series: ['4.2', '5.1'] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 2474780..dd277e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ * Add a --sync flag to the loaddivisions management command, to delete divisions that are in the DB but not the CSV, even if the DB contains the CSV. This flag is relevant if you synchronize with a single CSV. +## 3.4.0 (put the date here, I guess) + +* Support Django versions >=4.2 + ## 3.3.0 (2023-05-08) * Add last_seen field to database objects diff --git a/README.md b/README.md index 346cc63..30de33e 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ python-opencivicdata Python utilities (including Django models) for implementing the Open Civic Data specification. -**Requires Django >=2.2 and Python >= 3.6, pin to <3.0 for older versions** +**Requires Django >=4.2 and Python >= 3.6, pin to <3.0 for Django versions < 2.2 and < 3.3 for Django versions < 4.2 ** The Organization, Person, Membership, Post, and VoteEvent models and related models are based on the [Popolo specification](http://popoloproject.com/). diff --git a/opencivicdata/core/migrations/0001_initial.py b/opencivicdata/core/migrations/0001_initial.py index 44bf284..8823c1b 100644 --- a/opencivicdata/core/migrations/0001_initial.py +++ b/opencivicdata/core/migrations/0001_initial.py @@ -825,17 +825,19 @@ class Migration(migrations.Migration): to="core.Post", ), ), - migrations.AlterIndexTogether( - name="post", index_together=set([("organization", "label")]) + migrations.AddIndex( + model_name="post", index=django.db.models.Index(name="post", fields=["organization", "label"]) ), - migrations.AlterIndexTogether( - name="organization", - index_together=set( - [("classification", "name"), ("jurisdiction", "classification", "name")] - ), + migrations.AddIndex( + model_name="organization", + index=django.db.models.Index(name="organization_class_name", fields=["classification", "name"]) + ), + migrations.AddIndex( + model_name="organization", + index=django.db.models.Index(name="organization", fields=["jurisdiction", "classification", "name"]) ), - migrations.AlterIndexTogether( - name="membership", - index_together=set([("organization", "person", "label", "post")]), + migrations.AddIndex( + model_name="membership", + index=django.db.models.Index(name="membership", fields=["organization", "person", "label", "post"]) ), ] diff --git a/opencivicdata/core/models/base.py b/opencivicdata/core/models/base.py index 98799ee..0b6dc69 100644 --- a/opencivicdata/core/models/base.py +++ b/opencivicdata/core/models/base.py @@ -2,6 +2,7 @@ import re import uuid from django.db import models + from django.contrib.postgres.fields import ArrayField from django.core.validators import RegexValidator diff --git a/opencivicdata/core/models/people_orgs.py b/opencivicdata/core/models/people_orgs.py index 5917223..768defd 100644 --- a/opencivicdata/core/models/people_orgs.py +++ b/opencivicdata/core/models/people_orgs.py @@ -146,9 +146,9 @@ def get_current_members(self): class Meta: db_table = "opencivicdata_organization" - index_together = [ - ["jurisdiction", "classification", "name"], - ["classification", "name"], + indexes = [ + models.Index(fields=["jurisdiction", "classification", "name"]), + models.Index(fields=["classification", "name"]), ] @@ -280,7 +280,7 @@ class Post(OCDBase): class Meta: db_table = "opencivicdata_post" - index_together = [["organization", "label"]] + indexes = [models.Index(fields=["organization", "label"])] def __str__(self): return "{} - {} - {}".format(self.role, self.label, self.organization) @@ -549,7 +549,7 @@ class Membership(OCDBase): class Meta: db_table = "opencivicdata_membership" - index_together = [["organization", "person", "label", "post"]] + indexes = [models.Index(fields=["organization", "person", "label", "post"])] def __str__(self): return "{} in {} ({})".format(self.person, self.organization, self.role) diff --git a/opencivicdata/elections/models/candidacy.py b/opencivicdata/elections/models/candidacy.py index 4dea958..456502a 100644 --- a/opencivicdata/elections/models/candidacy.py +++ b/opencivicdata/elections/models/candidacy.py @@ -44,9 +44,10 @@ class Candidacy(OCDBase): filed_date = models.DateField( null=True, help_text="Specifies when the candidate filed for the contest." ) - is_incumbent = models.NullBooleanField( + is_incumbent = models.BooleanField( help_text="Indicates whether the candidate is seeking re-election to a " - "public office he/she currently holds" + "public office he/she currently holds", + null=True ) party = models.ForeignKey( Organization, diff --git a/opencivicdata/elections/models/contests/party.py b/opencivicdata/elections/models/contests/party.py index 3d622d1..006a325 100644 --- a/opencivicdata/elections/models/contests/party.py +++ b/opencivicdata/elections/models/contests/party.py @@ -49,8 +49,9 @@ class PartyContestOption(models.Model): help_text="Reference to an Organization representing a political party " "voters may choose in the contest.", ) - is_incumbent = models.NullBooleanField( - help_text="Indicates whether the party currently holds majority power." + is_incumbent = models.BooleanField( + help_text="Indicates whether the party currently holds majority power.", + null=True ) def __str__(self): diff --git a/opencivicdata/legislative/migrations/0001_initial.py b/opencivicdata/legislative/migrations/0001_initial.py index 3939ee3..6a21fce 100644 --- a/opencivicdata/legislative/migrations/0001_initial.py +++ b/opencivicdata/legislative/migrations/0001_initial.py @@ -1180,22 +1180,20 @@ class Migration(migrations.Migration): to="legislative.LegislativeSession", ), ), - migrations.AlterIndexTogether( - name="voteevent", - index_together=set( - [ - ("legislative_session", "bill"), - ("legislative_session", "identifier", "bill"), - ] - ), + migrations.AddIndex( + model_name="voteevent", + index=django.db.models.Index(name="voteevent_session_bill", fields=["legislative_session", "bill"]) ), - migrations.AlterIndexTogether( - name="event", index_together=set([("jurisdiction", "start_time", "name")]) + migrations.AddIndex( + model_name="voteevent", + index=django.db.models.Index(name="voteevent_session_id_bill", fields=["legislative_session", "identifier", "bill"]), ), - migrations.AlterIndexTogether( - name="bill", - index_together=set( - [("from_organization", "legislative_session", "identifier")] - ), + migrations.AddIndex( + model_name="event", + index=django.db.models.Index(name="event", fields=["jurisdiction", "start_time", "name"]) + ), + migrations.AddIndex( + model_name="bill", + index=django.db.models.Index(name="bill", fields=["from_organization", "legislative_session", "identifier"]) ), ] diff --git a/opencivicdata/legislative/migrations/0003_time_changes.py b/opencivicdata/legislative/migrations/0003_time_changes.py index 24af1be..aa91d4b 100644 --- a/opencivicdata/legislative/migrations/0003_time_changes.py +++ b/opencivicdata/legislative/migrations/0003_time_changes.py @@ -40,8 +40,8 @@ class Migration(migrations.Migration): migrations.RenameField( model_name="event", old_name="start_time", new_name="start_date" ), - migrations.AlterIndexTogether( - name="event", index_together=set([("jurisdiction", "start_date", "name")]) + migrations.AddIndex( + model_name="event", index=models.Index(name="event_juris_name", fields=["jurisdiction", "start_date", "name"]) ), migrations.RemoveField(model_name="event", name="timezone"), migrations.RunSQL( diff --git a/opencivicdata/legislative/models/bill.py b/opencivicdata/legislative/models/bill.py index f0cee7d..abfdb5b 100644 --- a/opencivicdata/legislative/models/bill.py +++ b/opencivicdata/legislative/models/bill.py @@ -47,7 +47,7 @@ def __str__(self): class Meta: db_table = "opencivicdata_bill" - index_together = [["from_organization", "legislative_session", "identifier"]] + indexes = [models.Index(fields=["from_organization", "legislative_session", "identifier"])] class BillAbstract(RelatedBase): diff --git a/opencivicdata/legislative/models/event.py b/opencivicdata/legislative/models/event.py index d78ac44..7a68489 100644 --- a/opencivicdata/legislative/models/event.py +++ b/opencivicdata/legislative/models/event.py @@ -70,7 +70,9 @@ def __str__(self): class Meta: db_table = "opencivicdata_event" - index_together = [["jurisdiction", "start_date", "name"]] + indexes = [ + models.Index(fields=["jurisdiction", "start_date", "name"]) + ] class EventMedia(EventMediaBase): diff --git a/opencivicdata/legislative/models/vote.py b/opencivicdata/legislative/models/vote.py index 10b0a5f..02ed378 100644 --- a/opencivicdata/legislative/models/vote.py +++ b/opencivicdata/legislative/models/vote.py @@ -58,9 +58,9 @@ def __str__(self): class Meta: db_table = "opencivicdata_voteevent" - index_together = [ - ["legislative_session", "identifier", "bill"], - ["legislative_session", "bill"], + indexes = [ + models.Index(fields=["legislative_session", "identifier", "bill"]), + models.Index(fields=["legislative_session", "bill"]), ] diff --git a/setup.py b/setup.py index d120d9d..80176c1 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from setuptools import setup, find_packages -install_requires = ["Django>=3.2", "psycopg2-binary"] +install_requires = ["Django>=4.2", "psycopg2-binary"] extras_require = { "dev": ["pytest>=3.6", "pytest-cov", "pytest-django", "coveralls==3.2.0", "flake8"]