Skip to content

Commit

Permalink
Replaces most of the backrefs with explicit relationships
Browse files Browse the repository at this point in the history
  • Loading branch information
Daverball authored Aug 2, 2024
1 parent b77c4e7 commit 9a31739
Show file tree
Hide file tree
Showing 24 changed files with 247 additions and 113 deletions.
17 changes: 9 additions & 8 deletions src/onegov/election_day/models/data_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from sqlalchemy import Enum
from sqlalchemy import ForeignKey
from sqlalchemy import Text
from sqlalchemy.orm import backref
from sqlalchemy.orm import object_session
from sqlalchemy.orm import relationship
from uuid import uuid4
Expand Down Expand Up @@ -71,7 +70,7 @@ class DataSource(Base, TimestampMixin):
"DataSourceItem",
cascade="all, delete-orphan",
lazy="dynamic",
backref=backref("source"),
back_populates="source",
)

@property
Expand Down Expand Up @@ -135,8 +134,8 @@ class DataSourceItem(Base, TimestampMixin):
)

election: 'relationship[Election | None]' = relationship(
"Election",
backref="data_sources"
'Election',
back_populates="data_sources"
)

#: the vote
Expand All @@ -147,12 +146,14 @@ class DataSourceItem(Base, TimestampMixin):
)

vote: 'relationship[Vote | None]' = relationship(
"Vote",
backref="data_sources"
'Vote',
back_populates="data_sources"
)

if TYPE_CHECKING:
source: relationship[DataSource]
source: 'relationship[DataSource]' = relationship(
DataSource,
back_populates='items'
)

@property
def item(self) -> Election | Vote | None:
Expand Down
27 changes: 25 additions & 2 deletions src/onegov/election_day/models/election/election.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
from onegov.election_day.models.mixins import StatusMixin
from onegov.election_day.models.mixins import summarized_property
from onegov.election_day.models.mixins import TitleTranslationsMixin
from onegov.election_day.models.party_result.mixins import \
PartyResultsOptionsMixin
from onegov.election_day.models.party_result.mixins import (
PartyResultsOptionsMixin)
from sqlalchemy import Column
from sqlalchemy import Date
from sqlalchemy import ForeignKey
Expand All @@ -33,8 +33,11 @@
import datetime
from collections.abc import Mapping
from onegov.core.types import AppenderQuery
from onegov.election_day.models import DataSourceItem
from onegov.election_day.models import ElectionCompound
from onegov.election_day.models import ElectionRelationship
from onegov.election_day.models import Notification
from onegov.election_day.models import Screen
from sqlalchemy.orm import Query
from sqlalchemy.sql import ColumnElement
from typing import NamedTuple
Expand Down Expand Up @@ -381,3 +384,23 @@ def clear_results(self, clear_all: bool = False) -> None:
).delete()
session.flush()
session.expire_all()

#: data source items linked to this election
data_sources: 'relationship[list[DataSourceItem]]' = relationship(
'DataSourceItem',
back_populates='election'
)

#: notifcations linked to this election
notifications: 'relationship[AppenderQuery[Notification]]'
notifications = relationship( # type:ignore[misc]
'onegov.election_day.models.notification.Notification',
back_populates='election',
lazy='dynamic'
)

#: screens linked to this election
screens: 'relationship[AppenderQuery[Screen]]' = relationship(
'Screen',
back_populates='election',
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
from onegov.core.orm.mixins import meta_property
from onegov.core.orm.types import HSTORE
from onegov.core.utils import groupbylist
from onegov.election_day.models.election_compound.mixins import \
DerivedAttributesMixin
from onegov.election_day.models.election_compound.mixins import (
DerivedAttributesMixin)
from onegov.election_day.models.mixins import DomainOfInfluenceMixin
from onegov.election_day.models.mixins import ExplanationsPdfMixin
from onegov.election_day.models.mixins import IdFromTitlesMixin
from onegov.election_day.models.mixins import LastModifiedMixin
from onegov.election_day.models.mixins import TitleTranslationsMixin
from onegov.election_day.models.party_result.mixins import \
HistoricalPartyResultsMixin
from onegov.election_day.models.party_result.mixins import \
PartyResultsCheckMixin
from onegov.election_day.models.party_result.mixins import \
PartyResultsOptionsMixin
from onegov.election_day.models.party_result.mixins import (
HistoricalPartyResultsMixin)
from onegov.election_day.models.party_result.mixins import (
PartyResultsCheckMixin)
from onegov.election_day.models.party_result.mixins import (
PartyResultsOptionsMixin)
from onegov.file import NamedFile
from sqlalchemy import Column, Boolean
from sqlalchemy import Date
Expand All @@ -33,8 +33,10 @@
from onegov.core.types import AppenderQuery
from onegov.election_day.models import Election
from onegov.election_day.models import ElectionCompoundRelationship
from onegov.election_day.models import Notification
from onegov.election_day.models import PartyPanachageResult
from onegov.election_day.models import PartyResult
from onegov.election_day.models import Screen
from onegov.election_day.types import DomainOfInfluence
import datetime

Expand Down Expand Up @@ -230,6 +232,20 @@ def elected_candidates(self) -> list[tuple[str, str]]:

return result

#: notifcations linked to this election compound
notifications: 'relationship[AppenderQuery[Notification]]'
notifications = relationship( # type:ignore[misc]
'onegov.election_day.models.notification.Notification',
back_populates='election_compound',
lazy='dynamic'
)

#: screens linked to this election compound
screens: 'relationship[AppenderQuery[Screen]]' = relationship(
'Screen',
back_populates='election_compound',
)

#: may be used to store a link related to this election
related_link: dict_property[str | None] = meta_property(
'related_link'
Expand Down
7 changes: 3 additions & 4 deletions src/onegov/election_day/models/notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from sqlalchemy import func
from sqlalchemy import or_
from sqlalchemy import Text
from sqlalchemy.orm import backref
from sqlalchemy.orm import relationship
from uuid import uuid4

Expand Down Expand Up @@ -78,7 +77,7 @@ class Notification(Base, TimestampMixin):
#: The corresponding election
election: 'relationship[Election | None]' = relationship(
'Election',
backref=backref('notifications', lazy='dynamic')
back_populates='notifications'
)

#: The corresponding election compound id
Expand All @@ -93,7 +92,7 @@ class Notification(Base, TimestampMixin):
#: The corresponding election compound
election_compound: 'relationship[ElectionCompound | None]' = relationship(
'ElectionCompound',
backref=backref('notifications', lazy='dynamic')
back_populates='notifications'
)

#: The corresponding vote id
Expand All @@ -106,7 +105,7 @@ class Notification(Base, TimestampMixin):
#: The corresponding vote
vote: 'relationship[Vote | None]' = relationship(
'Vote',
backref=backref('notifications', lazy='dynamic')
back_populates='notifications'
)

def update_from_model(
Expand Down
6 changes: 3 additions & 3 deletions src/onegov/election_day/models/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class Screen(Base, ContentMixin, TimestampMixin):
)
vote: 'relationship[Vote | None]' = relationship(
'Vote',
backref='screens'
back_populates='screens'
)

#: The election
Expand All @@ -77,7 +77,7 @@ class Screen(Base, ContentMixin, TimestampMixin):
)
election: 'relationship[Election | None]' = relationship(
'Election',
backref='screens'
back_populates='screens'
)

#: The election compound
Expand All @@ -87,7 +87,7 @@ class Screen(Base, ContentMixin, TimestampMixin):
)
election_compound: 'relationship[ElectionCompound | None]' = relationship(
'ElectionCompound',
backref='screens'
back_populates='screens'
)

#: The domain of the election compound part.
Expand Down
24 changes: 24 additions & 0 deletions src/onegov/election_day/models/vote/vote.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
if TYPE_CHECKING:
import datetime
from collections.abc import Mapping
from onegov.core.types import AppenderQuery
from onegov.election_day.models import DataSourceItem
from onegov.election_day.models import Notification
from onegov.election_day.models import Screen
from onegov.election_day.types import BallotType
from sqlalchemy.sql import ColumnElement

Expand Down Expand Up @@ -305,6 +309,26 @@ def last_modified(cls) -> 'ColumnElement[datetime.datetime | None]':
cls.last_change, cls.last_result_change, cls.last_ballot_change
)

#: data source items linked to this vote
data_sources: 'relationship[list[DataSourceItem]]' = relationship(
'DataSourceItem',
back_populates='vote'
)

#: notifcations linked to this vote
notifications: 'relationship[AppenderQuery[Notification]]'
notifications = relationship( # type:ignore[misc]
'onegov.election_day.models.notification.Notification',
back_populates='vote',
lazy='dynamic'
)

#: screens linked to this vote
screens: 'relationship[AppenderQuery[Screen]]' = relationship(
'Screen',
back_populates='vote',
)

#: may be used to store a link related to this vote
related_link: dict_property[str | None] = meta_property('related_link')

Expand Down
4 changes: 2 additions & 2 deletions src/onegov/election_day/views/upload/election.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def view_upload_majorz_election(
)
elif form.file_format.data == 'wabsti_c':
source: DataSourceItem
for source in self.data_sources: # type:ignore[attr-defined]
for source in self.data_sources:
assert source.district is not None
assert source.number is not None
assert form.wm_wahl.data is not None
Expand Down Expand Up @@ -182,7 +182,7 @@ def view_upload_proporz_election(
)
elif form.file_format.data == 'wabsti_c':
source: DataSourceItem
for source in self.data_sources: # type:ignore[attr-defined]
for source in self.data_sources:
assert source.number is not None
assert form.wp_wahl.data is not None
assert form.wp_wahl.file is not None
Expand Down
2 changes: 1 addition & 1 deletion src/onegov/election_day/views/upload/vote.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def view_upload(
assert form.sg_gemeinden.data is not None
assert form.sg_gemeinden.file is not None
source: DataSourceItem
for source in self.data_sources: # type:ignore[attr-defined]
for source in self.data_sources:
assert source.number is not None
assert source.district is not None
errors.extend(
Expand Down
12 changes: 7 additions & 5 deletions src/onegov/file/models/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from onegov.file.attachments import ProcessedUploadedFile
from onegov.file.filters import OnlyIfImage, WithThumbnailFilter
from onegov.file.filters import OnlyIfPDF, WithPDFThumbnailFilter
from onegov.file.models.fileset import file_to_set_associations
from onegov.file.utils import extension_for_content_type
from onegov.search import ORMSearchable
from pathlib import Path
Expand All @@ -25,7 +26,7 @@
from sqlalchemy import text
from sqlalchemy import type_coerce
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import deferred
from sqlalchemy.orm import deferred, relationship
from sqlalchemy.orm import object_session, Session
from sqlalchemy.orm.attributes import flag_modified
from time import monotonic
Expand All @@ -41,7 +42,6 @@
from onegov.file import FileSet
from onegov.file.types import FileStats, SignatureMetadata
from sqlalchemy.engine import Dialect
from sqlalchemy.orm import relationship
from sqlalchemy.orm.session import SessionTransaction
from sqlalchemy.sql.type_api import TypeEngine

Expand Down Expand Up @@ -252,9 +252,11 @@ class File(Base, Associable, TimestampMixin):
#: store additional information using e.g. `meta_property`
meta: 'Column[dict[str, Any]]' = Column(JSON, nullable=False, default=dict)

if TYPE_CHECKING:
# forward declare backref
filesets: 'relationship[list[FileSet]]'
filesets: 'relationship[list[FileSet]]' = relationship(
'FileSet',
secondary=file_to_set_associations,
back_populates='files'
)

__mapper_args__ = {
'polymorphic_on': 'type',
Expand Down
2 changes: 1 addition & 1 deletion src/onegov/file/models/fileset.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class FileSet(Base, ContentMixin, TimestampMixin):
files: 'relationship[list[File]]' = relationship(
'File',
secondary=file_to_set_associations,
backref='filesets',
back_populates='filesets',
order_by='desc(File.last_change)'
)

Expand Down
8 changes: 4 additions & 4 deletions src/onegov/form/models/definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,14 @@ def id(self) -> str:
#: link between forms and submissions
submissions: 'relationship[list[FormSubmission]]' = relationship(
FormSubmission,
backref='form'
back_populates='form'
)

#: link between forms and registration windows
registration_windows: 'relationship[list[FormRegistrationWindow]]'
registration_windows = relationship(
FormRegistrationWindow,
backref='form',
back_populates='form',
order_by='FormRegistrationWindow.start',
cascade='all, delete-orphan'
)
Expand Down Expand Up @@ -257,14 +257,14 @@ def id(self) -> str:
#: link between surveys and submissions
submissions: 'relationship[list[SurveySubmission]]' = relationship(
SurveySubmission,
backref='survey'
back_populates='survey'
)

#: link between surveys and submission windows
submission_windows: 'relationship[list[SurveySubmissionWindow]]'
submission_windows = relationship(
SurveySubmissionWindow,
backref='survey',
back_populates='survey',
order_by='SurveySubmissionWindow.start',
cascade='all, delete-orphan'
)
Expand Down
14 changes: 8 additions & 6 deletions src/onegov/form/models/registration_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ class FormRegistrationWindow(Base, TimestampMixin):
nullable=False
)

#: the form to which this registration window belongs
form: 'relationship[FormDefinition]' = relationship(
'FormDefinition',
back_populates='registration_windows'
)

#: true if the registration window is enabled
enabled: 'Column[bool]' = Column(Boolean, nullable=False, default=True)

Expand All @@ -80,16 +86,12 @@ class FormRegistrationWindow(Base, TimestampMixin):
#: enable an overflow of submissions
overflow: 'Column[bool]' = Column(Boolean, nullable=False, default=True)

#: submissions linked to this
#: submissions linked to this registration window
submissions: 'relationship[list[FormSubmission]]' = relationship(
FormSubmission,
backref='registration_window'
back_populates='registration_window'
)

if TYPE_CHECKING:
# forward declare backref
form: relationship[FormDefinition]

__table_args__ = (

# ensures that there are no overlapping date ranges within one form
Expand Down
Loading

0 comments on commit 9a31739

Please sign in to comment.