From f3b2cb79f18650dbaaca1be68c73e4311bd5764a Mon Sep 17 00:00:00 2001 From: Joshua Sangmeister Date: Tue, 26 Mar 2024 12:23:40 +0100 Subject: [PATCH 1/9] Update model generation to relational models.yml --- cli/generate_models.py | 46 +-- docs/actions/meeting.update.md | 2 +- global/data/example-data.json | 4 +- global/meta | 2 +- openslides_backend/models/fields.py | 3 + openslides_backend/models/mixins.py | 2 +- openslides_backend/models/models.py | 479 ++++++++++++++++++++-------- 7 files changed, 381 insertions(+), 157 deletions(-) diff --git a/cli/generate_models.py b/cli/generate_models.py index 641ea9737..6c33a7880 100644 --- a/cli/generate_models.py +++ b/cli/generate_models.py @@ -199,7 +199,8 @@ class Attribute(Node): default: Any = None on_delete: OnDelete | None = None equal_fields: str | list[str] | None = None - contraints: dict[str, Any] + constraints: dict[str, Any] + is_view_field: bool = False FIELD_TEMPLATE = string.Template( " ${field_name} = fields.${field_class}(${properties})\n" @@ -210,38 +211,39 @@ def __init__(self, value: str | dict) -> None: **COMMON_FIELD_CLASSES, **RELATION_FIELD_CLASSES, } - self.contraints = {} + self.constraints = {} self.in_array_constraints = {} if isinstance(value, str): self.type = value else: - self.type = value.get("type", "") + self.type = value.pop("type") if self.type in RELATION_FIELD_CLASSES.keys(): - self.to = To(value.get("to", {})) - self.on_delete = value.get("on_delete") + self.to = To(value.pop("to")) + self.on_delete = value.pop("on_delete", None) + if self.type in ("relation-list", "generic-relation-list") or value.get( + "sql" + ): + self.is_view_field = True else: assert self.type in COMMON_FIELD_CLASSES.keys(), ( "Invalid type: " + self.type ) - self.required = value.get("required", False) - self.read_only = value.get("read_only", False) - self.constant = value.get("constant", False) - self.default = value.get("default") - self.equal_fields = value.get("equal_fields") + self.required = value.pop("required", False) + self.read_only = value.pop("read_only", False) + self.constant = value.pop("constant", False) + self.default = value.pop("default", None) + self.equal_fields = value.pop("equal_fields", None) for k, v in value.items(): if k not in ( - "type", - "to", - "required", - "read_only", - "constant", - "default", - "on_delete", - "equal_fields", "items", "restriction_mode", + # database metadata + "reference", + "sql", + "deferred", + "unique", ): - self.contraints[k] = v + self.constraints[k] = v elif self.type in ("string[]", "number[]") and k == "items": self.in_array_constraints.update(v) @@ -256,6 +258,8 @@ def get_code(self, field_name: str) -> str: if self.on_delete: assert self.on_delete in [mode for mode in OnDelete] properties += f"on_delete=fields.OnDelete.{self.on_delete}, " + if self.is_view_field: + properties += "is_view_field=True, " if self.required: properties += "required=True, " if self.read_only: @@ -266,8 +270,8 @@ def get_code(self, field_name: str) -> str: properties += f"default={repr(self.default)}, " if self.equal_fields is not None: properties += f"equal_fields={repr(self.equal_fields)}, " - if self.contraints: - properties += f"constraints={repr(self.contraints)}, " + if self.constraints: + properties += f"constraints={repr(self.constraints)}, " if self.in_array_constraints and self.type in ("string[]", "number[]"): properties += f"in_array_constraints={repr(self.in_array_constraints)}" return self.FIELD_TEMPLATE.substitute( diff --git a/docs/actions/meeting.update.md b/docs/actions/meeting.update.md index 7cb06ec21..4a68ff86d 100644 --- a/docs/actions/meeting.update.md +++ b/docs/actions/meeting.update.md @@ -154,7 +154,7 @@ default_projector_agenda_item_list_ids: Ids; default_projector_topic_ids: Ids; default_projector_list_of_speakers_ids: Ids; - default_projector_current_list_of_speakers_ids: Ids; + default_projector_current_los_ids: Ids; default_projector_motion_ids: Ids; default_projector_amendment_ids: Ids; default_projector_motion_block_ids: Ids; diff --git a/global/data/example-data.json b/global/data/example-data.json index b29f727e1..22b0a2198 100644 --- a/global/data/example-data.json +++ b/global/data/example-data.json @@ -574,7 +574,7 @@ "default_projector_agenda_item_list_ids": [1], "default_projector_topic_ids": [1], "default_projector_list_of_speakers_ids": [2], - "default_projector_current_list_of_speakers_ids": [2], + "default_projector_current_los_ids": [2], "default_projector_motion_ids": [1], "default_projector_amendment_ids": [1], "default_projector_motion_block_ids": [1], @@ -2409,7 +2409,7 @@ "show_clock": true, "sequential_number": 2, "used_as_default_projector_for_list_of_speakers_in_meeting_id": 1, - "used_as_default_projector_for_current_list_of_speakers_in_meeting_id": 1, + "used_as_default_projector_for_current_los_in_meeting_id": 1, "meeting_id": 1 } }, diff --git a/global/meta b/global/meta index 5a23cf2e6..c85ac7c24 160000 --- a/global/meta +++ b/global/meta @@ -1 +1 @@ -Subproject commit 5a23cf2e664e91bae453e64fa5ecfb0eba92f4e8 +Subproject commit c85ac7c24741ba2ae9f7d1fdf8abb36c37ed2333 diff --git a/openslides_backend/models/fields.py b/openslides_backend/models/fields.py index d2c920427..0f3bccbe4 100644 --- a/openslides_backend/models/fields.py +++ b/openslides_backend/models/fields.py @@ -44,6 +44,7 @@ class Field: constant: bool default: str | None constraints: dict[str, Any] + is_view_field: bool def __init__( self, @@ -52,6 +53,7 @@ def __init__( constant: bool = False, default: Any | None = None, constraints: dict[str, Any] | None = None, + is_view_field: bool = False, ) -> None: self.required = required self.read_only = read_only @@ -60,6 +62,7 @@ def __init__( if not self.required and constraints and "enum" in constraints: constraints["enum"].append(None) self.constraints = constraints or {} + self.is_view_field = is_view_field self.schema_validator = fastjsonschema.compile(self.get_schema()) def get_schema(self) -> Schema: diff --git a/openslides_backend/models/mixins.py b/openslides_backend/models/mixins.py index c7cd17fa0..d1953de78 100644 --- a/openslides_backend/models/mixins.py +++ b/openslides_backend/models/mixins.py @@ -29,7 +29,7 @@ class MeetingModelMixin: "agenda_item_list", "topic", "list_of_speakers", - "current_list_of_speakers", + "current_los", "motion", "amendment", "motion_block", diff --git a/openslides_backend/models/models.py b/openslides_backend/models/models.py index 8aba2d767..12ae5423d 100644 --- a/openslides_backend/models/models.py +++ b/openslides_backend/models/models.py @@ -42,27 +42,35 @@ class Organization(Model): saml_metadata_idp = fields.TextField() saml_metadata_sp = fields.TextField() saml_private_key = fields.TextField() - committee_ids = fields.RelationListField(to={"committee": "organization_id"}) + committee_ids = fields.RelationListField( + to={"committee": "organization_id"}, is_view_field=True + ) active_meeting_ids = fields.RelationListField( - to={"meeting": "is_active_in_organization_id"} + to={"meeting": "is_active_in_organization_id"}, is_view_field=True ) archived_meeting_ids = fields.RelationListField( - to={"meeting": "is_archived_in_organization_id"} + to={"meeting": "is_archived_in_organization_id"}, is_view_field=True ) template_meeting_ids = fields.RelationListField( - to={"meeting": "template_for_organization_id"} + to={"meeting": "template_for_organization_id"}, is_view_field=True ) organization_tag_ids = fields.RelationListField( - to={"organization_tag": "organization_id"} + to={"organization_tag": "organization_id"}, is_view_field=True ) theme_id = fields.RelationField( to={"theme": "theme_for_organization_id"}, required=True ) - theme_ids = fields.RelationListField(to={"theme": "organization_id"}) + theme_ids = fields.RelationListField( + to={"theme": "organization_id"}, is_view_field=True + ) mediafile_ids = fields.RelationListField( - to={"mediafile": "owner_id"}, on_delete=fields.OnDelete.CASCADE + to={"mediafile": "owner_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, + ) + user_ids = fields.RelationListField( + to={"user": "organization_id"}, is_view_field=True ) - user_ids = fields.RelationListField(to={"user": "organization_id"}) users_email_sender = fields.CharField(default="OpenSlides") users_email_replyto = fields.CharField() users_email_subject = fields.CharField(default="OpenSlides access data") @@ -108,25 +116,39 @@ class User(Model): } ) is_present_in_meeting_ids = fields.RelationListField( - to={"meeting": "present_user_ids"} + to={"meeting": "present_user_ids"}, is_view_field=True ) - committee_ids = fields.RelationListField( - to={"committee": "user_ids"}, + committee_ids = fields.NumberArrayField( read_only=True, - constraints={"description": "Calculated field."}, + constraints={ + "to": "committee/user_ids", + "description": "Calculated field: Returns committee_ids, where the user is manager or member in a meeting", + }, + ) + committee_management_ids = fields.RelationListField( + to={"committee": "manager_ids"}, is_view_field=True ) - committee_management_ids = fields.RelationListField(to={"committee": "manager_ids"}) forwarding_committee_ids = fields.RelationListField( - to={"committee": "forwarding_user_id"} + to={"committee": "forwarding_user_id"}, is_view_field=True ) meeting_user_ids = fields.RelationListField( - to={"meeting_user": "user_id"}, on_delete=fields.OnDelete.CASCADE + to={"meeting_user": "user_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, + ) + poll_voted_ids = fields.RelationListField( + to={"poll": "voted_ids"}, is_view_field=True + ) + option_ids = fields.RelationListField( + to={"option": "content_object_id"}, is_view_field=True + ) + vote_ids = fields.RelationListField(to={"vote": "user_id"}, is_view_field=True) + delegated_vote_ids = fields.RelationListField( + to={"vote": "delegated_user_id"}, is_view_field=True + ) + poll_candidate_ids = fields.RelationListField( + to={"poll_candidate": "user_id"}, is_view_field=True ) - poll_voted_ids = fields.RelationListField(to={"poll": "voted_ids"}) - option_ids = fields.RelationListField(to={"option": "content_object_id"}) - vote_ids = fields.RelationListField(to={"vote": "user_id"}) - delegated_vote_ids = fields.RelationListField(to={"vote": "delegated_user_id"}) - poll_candidate_ids = fields.RelationListField(to={"poll_candidate": "user_id"}) meeting_ids = fields.NumberArrayField( read_only=True, constraints={ @@ -156,43 +178,58 @@ class MeetingUser(Model): personal_note_ids = fields.RelationListField( to={"personal_note": "meeting_user_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) speaker_ids = fields.RelationListField( - to={"speaker": "meeting_user_id"}, equal_fields="meeting_id" + to={"speaker": "meeting_user_id"}, is_view_field=True, equal_fields="meeting_id" ) supported_motion_ids = fields.RelationListField( - to={"motion": "supporter_meeting_user_ids"}, equal_fields="meeting_id" + to={"motion": "supporter_meeting_user_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) motion_editor_ids = fields.RelationListField( - to={"motion_editor": "meeting_user_id"}, equal_fields="meeting_id" + to={"motion_editor": "meeting_user_id"}, + is_view_field=True, + equal_fields="meeting_id", ) motion_working_group_speaker_ids = fields.RelationListField( to={"motion_working_group_speaker": "meeting_user_id"}, + is_view_field=True, equal_fields="meeting_id", ) motion_submitter_ids = fields.RelationListField( to={"motion_submitter": "meeting_user_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) assignment_candidate_ids = fields.RelationListField( - to={"assignment_candidate": "meeting_user_id"}, equal_fields="meeting_id" + to={"assignment_candidate": "meeting_user_id"}, + is_view_field=True, + equal_fields="meeting_id", ) vote_delegated_to_id = fields.RelationField( to={"meeting_user": "vote_delegations_from_ids"}, equal_fields="meeting_id" ) vote_delegations_from_ids = fields.RelationListField( - to={"meeting_user": "vote_delegated_to_id"}, equal_fields="meeting_id" + to={"meeting_user": "vote_delegated_to_id"}, + is_view_field=True, + equal_fields="meeting_id", ) chat_message_ids = fields.RelationListField( - to={"chat_message": "meeting_user_id"}, equal_fields="meeting_id" + to={"chat_message": "meeting_user_id"}, + is_view_field=True, + equal_fields="meeting_id", ) group_ids = fields.RelationListField( - to={"group": "meeting_user_ids"}, equal_fields="meeting_id" + to={"group": "meeting_user_ids"}, is_view_field=True, equal_fields="meeting_id" ) structure_level_ids = fields.RelationListField( - to={"structure_level": "meeting_user_ids"}, equal_fields="meeting_id" + to={"structure_level": "meeting_user_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) @@ -204,7 +241,8 @@ class OrganizationTag(Model): name = fields.CharField(required=True) color = fields.ColorField(required=True) tagged_ids = fields.GenericRelationListField( - to={"committee": "organization_tag_ids", "meeting": "organization_tag_ids"} + to={"committee": "organization_tag_ids", "meeting": "organization_tag_ids"}, + is_view_field=True, ) organization_id = fields.OrganizationField( to={"organization": "organization_tag_ids"}, required=True @@ -265,7 +303,7 @@ class Theme(Model): abstain = fields.ColorField() theme_for_organization_id = fields.RelationField(to={"organization": "theme_id"}) organization_id = fields.OrganizationField( - to={"organization": "theme_ids"}, required=True, constant=True + to={"organization": "theme_ids"}, required=True ) @@ -278,26 +316,32 @@ class Committee(Model): description = fields.HTMLStrictField() external_id = fields.CharField(constraints={"description": "unique"}) meeting_ids = fields.RelationListField( - to={"meeting": "committee_id"}, on_delete=fields.OnDelete.PROTECT + to={"meeting": "committee_id"}, + on_delete=fields.OnDelete.PROTECT, + is_view_field=True, ) default_meeting_id = fields.RelationField( to={"meeting": "default_meeting_for_committee_id"} ) - user_ids = fields.RelationListField( - to={"user": "committee_ids"}, + user_ids = fields.NumberArrayField( read_only=True, - constraints={"description": "Calculated field."}, + constraints={ + "to": "user/committee_ids", + "description": "Calculated field: All users which are in a group of a meeting, belonging to the committee or beeing manager of the committee", + }, + ) + manager_ids = fields.RelationListField( + to={"user": "committee_management_ids"}, is_view_field=True ) - manager_ids = fields.RelationListField(to={"user": "committee_management_ids"}) forward_to_committee_ids = fields.RelationListField( - to={"committee": "receive_forwardings_from_committee_ids"} + to={"committee": "receive_forwardings_from_committee_ids"}, is_view_field=True ) receive_forwardings_from_committee_ids = fields.RelationListField( - to={"committee": "forward_to_committee_ids"} + to={"committee": "forward_to_committee_ids"}, is_view_field=True ) forwarding_user_id = fields.RelationField(to={"user": "forwarding_committee_ids"}) organization_tag_ids = fields.RelationListField( - to={"organization_tag": "tagged_ids"} + to={"organization_tag": "tagged_ids"}, is_view_field=True ) organization_id = fields.OrganizationField( to={"organization": "committee_ids"}, required=True, constant=True @@ -373,7 +417,7 @@ class Meeting(Model, MeetingModelMixin): export_pdf_pagenumber_alignment = fields.CharField( default="center", constraints={"enum": ["left", "right", "center"]} ) - export_pdf_fontsize = fields.IntegerField( + export_pdf_fontsize = fields.CharField( default=10, constraints={"enum": [10, 11, 12]} ) export_pdf_line_height = fields.FloatField( @@ -531,17 +575,21 @@ class Meeting(Model, MeetingModelMixin): }, ) motion_poll_default_group_ids = fields.RelationListField( - to={"group": "used_as_motion_poll_default_id"} + to={"group": "used_as_motion_poll_default_id"}, is_view_field=True ) motion_poll_default_backend = fields.CharField( default="fast", constraints={"enum": ["long", "fast"]} ) poll_candidate_list_ids = fields.RelationListField( - to={"poll_candidate_list": "meeting_id"} + to={"poll_candidate_list": "meeting_id"}, is_view_field=True + ) + poll_candidate_ids = fields.RelationListField( + to={"poll_candidate": "meeting_id"}, is_view_field=True ) - poll_candidate_ids = fields.RelationListField(to={"poll_candidate": "meeting_id"}) meeting_user_ids = fields.RelationListField( - to={"meeting_user": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"meeting_user": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) users_enable_presence_view = fields.BooleanField(default=False) users_enable_vote_weight = fields.BooleanField(default=False) @@ -599,7 +647,7 @@ class Meeting(Model, MeetingModelMixin): }, ) assignment_poll_default_group_ids = fields.RelationListField( - to={"group": "used_as_assignment_poll_default_id"} + to={"group": "used_as_assignment_poll_default_id"}, is_view_field=True ) assignment_poll_default_backend = fields.CharField( default="fast", constraints={"enum": ["long", "fast"]} @@ -634,122 +682,183 @@ class Meeting(Model, MeetingModelMixin): }, ) poll_default_group_ids = fields.RelationListField( - to={"group": "used_as_poll_default_id"} + to={"group": "used_as_poll_default_id"}, is_view_field=True ) poll_default_backend = fields.CharField( default="fast", constraints={"enum": ["long", "fast"]} ) poll_couple_countdown = fields.BooleanField(default=True) topic_poll_default_group_ids = fields.RelationListField( - to={"group": "used_as_topic_poll_default_id"} + to={"group": "used_as_topic_poll_default_id"}, is_view_field=True ) projector_ids = fields.RelationListField( - to={"projector": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"projector": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) all_projection_ids = fields.RelationListField( - to={"projection": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"projection": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) projector_message_ids = fields.RelationListField( - to={"projector_message": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"projector_message": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) projector_countdown_ids = fields.RelationListField( - to={"projector_countdown": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"projector_countdown": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) tag_ids = fields.RelationListField( - to={"tag": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"tag": "meeting_id"}, on_delete=fields.OnDelete.CASCADE, is_view_field=True ) agenda_item_ids = fields.RelationListField( - to={"agenda_item": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"agenda_item": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) list_of_speakers_ids = fields.RelationListField( - to={"list_of_speakers": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"list_of_speakers": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) structure_level_list_of_speakers_ids = fields.RelationListField( to={"structure_level_list_of_speakers": "meeting_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) point_of_order_category_ids = fields.RelationListField( - to={"point_of_order_category": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"point_of_order_category": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) speaker_ids = fields.RelationListField( - to={"speaker": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"speaker": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) topic_ids = fields.RelationListField( - to={"topic": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"topic": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) group_ids = fields.RelationListField( - to={"group": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"group": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) mediafile_ids = fields.RelationListField( - to={"mediafile": "owner_id"}, on_delete=fields.OnDelete.CASCADE + to={"mediafile": "owner_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) motion_ids = fields.RelationListField( - to={"motion": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"motion": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) forwarded_motion_ids = fields.RelationListField( - to={"motion": "origin_meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"motion": "origin_meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) motion_comment_section_ids = fields.RelationListField( - to={"motion_comment_section": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"motion_comment_section": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) motion_category_ids = fields.RelationListField( - to={"motion_category": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"motion_category": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) motion_block_ids = fields.RelationListField( - to={"motion_block": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"motion_block": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) motion_workflow_ids = fields.RelationListField( - to={"motion_workflow": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"motion_workflow": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) motion_statute_paragraph_ids = fields.RelationListField( - to={"motion_statute_paragraph": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"motion_statute_paragraph": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) motion_comment_ids = fields.RelationListField( - to={"motion_comment": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"motion_comment": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) motion_submitter_ids = fields.RelationListField( - to={"motion_submitter": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"motion_submitter": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) motion_editor_ids = fields.RelationListField( - to={"motion_editor": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"motion_editor": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) motion_working_group_speaker_ids = fields.RelationListField( to={"motion_working_group_speaker": "meeting_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) motion_change_recommendation_ids = fields.RelationListField( to={"motion_change_recommendation": "meeting_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) motion_state_ids = fields.RelationListField( - to={"motion_state": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"motion_state": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) poll_ids = fields.RelationListField( - to={"poll": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"poll": "meeting_id"}, on_delete=fields.OnDelete.CASCADE, is_view_field=True ) option_ids = fields.RelationListField( - to={"option": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"option": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) vote_ids = fields.RelationListField( - to={"vote": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"vote": "meeting_id"}, on_delete=fields.OnDelete.CASCADE, is_view_field=True ) assignment_ids = fields.RelationListField( - to={"assignment": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"assignment": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) assignment_candidate_ids = fields.RelationListField( - to={"assignment_candidate": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"assignment_candidate": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) personal_note_ids = fields.RelationListField( - to={"personal_note": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"personal_note": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) chat_group_ids = fields.RelationListField( - to={"chat_group": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"chat_group": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) chat_message_ids = fields.RelationListField( - to={"chat_message": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"chat_message": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) structure_level_ids = fields.RelationListField( - to={"structure_level": "meeting_id"}, on_delete=fields.OnDelete.CASCADE + to={"structure_level": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) logo_projector_main_id = fields.RelationField( to={"mediafile": "used_as_logo_projector_main_in_meeting_id"} @@ -767,10 +876,10 @@ class Meeting(Model, MeetingModelMixin): to={"mediafile": "used_as_logo_pdf_header_r_in_meeting_id"} ) logo_pdf_footer_l_id = fields.RelationField( - to={"mediafile": "used_as_logo_pdf_footer_l_in_meeting_id"} + to={"mediafile": "used_as_logo_pdf_header_l_in_meeting_id"} ) logo_pdf_footer_r_id = fields.RelationField( - to={"mediafile": "used_as_logo_pdf_footer_r_in_meeting_id"} + to={"mediafile": "used_as_logo_pdf_header_l_in_meeting_id"} ) logo_pdf_ballot_paper_id = fields.RelationField( to={"mediafile": "used_as_logo_pdf_ballot_paper_in_meeting_id"} @@ -806,10 +915,10 @@ class Meeting(Model, MeetingModelMixin): to={"committee": "default_meeting_id"} ) organization_tag_ids = fields.RelationListField( - to={"organization_tag": "tagged_ids"} + to={"organization_tag": "tagged_ids"}, is_view_field=True ) present_user_ids = fields.RelationListField( - to={"user": "is_present_in_meeting_ids"} + to={"user": "is_present_in_meeting_ids"}, is_view_field=True ) user_ids = fields.NumberArrayField( read_only=True, @@ -827,68 +936,82 @@ class Meeting(Model, MeetingModelMixin): to={"projector_countdown": "used_as_poll_countdown_meeting_id"} ) projection_ids = fields.RelationListField( - to={"projection": "content_object_id"}, on_delete=fields.OnDelete.CASCADE + to={"projection": "content_object_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) default_projector_agenda_item_list_ids = fields.RelationListField( to={ "projector": "used_as_default_projector_for_agenda_item_list_in_meeting_id" }, + is_view_field=True, required=True, ) default_projector_topic_ids = fields.RelationListField( to={"projector": "used_as_default_projector_for_topic_in_meeting_id"}, + is_view_field=True, required=True, ) default_projector_list_of_speakers_ids = fields.RelationListField( to={ "projector": "used_as_default_projector_for_list_of_speakers_in_meeting_id" }, + is_view_field=True, required=True, ) - default_projector_current_list_of_speakers_ids = fields.RelationListField( - to={ - "projector": "used_as_default_projector_for_current_list_of_speakers_in_meeting_id" - }, + default_projector_current_los_ids = fields.RelationListField( + to={"projector": "used_as_default_projector_for_current_los_in_meeting_id"}, + is_view_field=True, required=True, ) default_projector_motion_ids = fields.RelationListField( to={"projector": "used_as_default_projector_for_motion_in_meeting_id"}, + is_view_field=True, required=True, ) default_projector_amendment_ids = fields.RelationListField( to={"projector": "used_as_default_projector_for_amendment_in_meeting_id"}, + is_view_field=True, required=True, ) default_projector_motion_block_ids = fields.RelationListField( to={"projector": "used_as_default_projector_for_motion_block_in_meeting_id"}, + is_view_field=True, required=True, ) default_projector_assignment_ids = fields.RelationListField( to={"projector": "used_as_default_projector_for_assignment_in_meeting_id"}, + is_view_field=True, required=True, ) default_projector_mediafile_ids = fields.RelationListField( to={"projector": "used_as_default_projector_for_mediafile_in_meeting_id"}, + is_view_field=True, required=True, ) default_projector_message_ids = fields.RelationListField( to={"projector": "used_as_default_projector_for_message_in_meeting_id"}, + is_view_field=True, required=True, ) default_projector_countdown_ids = fields.RelationListField( to={"projector": "used_as_default_projector_for_countdown_in_meeting_id"}, + is_view_field=True, required=True, ) default_projector_assignment_poll_ids = fields.RelationListField( to={"projector": "used_as_default_projector_for_assignment_poll_in_meeting_id"}, + is_view_field=True, required=True, ) default_projector_motion_poll_ids = fields.RelationListField( to={"projector": "used_as_default_projector_for_motion_poll_in_meeting_id"}, + is_view_field=True, required=True, ) default_projector_poll_ids = fields.RelationListField( to={"projector": "used_as_default_projector_for_poll_in_meeting_id"}, + is_view_field=True, required=True, ) default_group_id = fields.RelationField( @@ -906,10 +1029,13 @@ class StructureLevel(Model): color = fields.ColorField() default_time = fields.IntegerField(constraints={"minimum": 0}) meeting_user_ids = fields.RelationListField( - to={"meeting_user": "structure_level_ids"}, equal_fields="meeting_id" + to={"meeting_user": "structure_level_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) structure_level_list_of_speakers_ids = fields.RelationListField( to={"structure_level_list_of_speakers": "structure_level_id"}, + is_view_field=True, equal_fields="meeting_id", ) meeting_id = fields.RelationField( @@ -971,7 +1097,7 @@ class Group(Model): ) weight = fields.IntegerField() meeting_user_ids = fields.RelationListField( - to={"meeting_user": "group_ids"}, equal_fields="meeting_id" + to={"meeting_user": "group_ids"}, is_view_field=True, equal_fields="meeting_id" ) default_group_for_meeting_id = fields.RelationField( to={"meeting": "default_group_id"}, on_delete=fields.OnDelete.PROTECT @@ -980,27 +1106,38 @@ class Group(Model): to={"meeting": "admin_group_id"}, on_delete=fields.OnDelete.PROTECT ) mediafile_access_group_ids = fields.RelationListField( - to={"mediafile": "access_group_ids"}, equal_fields="meeting_id" + to={"mediafile": "access_group_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) mediafile_inherited_access_group_ids = fields.RelationListField( to={"mediafile": "inherited_access_group_ids"}, + is_view_field=True, read_only=True, constraints={"description": "Calculated field."}, ) read_comment_section_ids = fields.RelationListField( - to={"motion_comment_section": "read_group_ids"}, equal_fields="meeting_id" + to={"motion_comment_section": "read_group_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) write_comment_section_ids = fields.RelationListField( - to={"motion_comment_section": "write_group_ids"}, equal_fields="meeting_id" + to={"motion_comment_section": "write_group_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) read_chat_group_ids = fields.RelationListField( - to={"chat_group": "read_group_ids"}, equal_fields="meeting_id" + to={"chat_group": "read_group_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) write_chat_group_ids = fields.RelationListField( - to={"chat_group": "write_group_ids"}, equal_fields="meeting_id" + to={"chat_group": "write_group_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) poll_ids = fields.RelationListField( - to={"poll": "entitled_group_ids"}, equal_fields="meeting_id" + to={"poll": "entitled_group_ids"}, is_view_field=True, equal_fields="meeting_id" ) used_as_motion_poll_default_id = fields.RelationField( to={"meeting": "motion_poll_default_group_ids"} @@ -1048,6 +1185,7 @@ class Tag(Model): name = fields.CharField(required=True) tagged_ids = fields.GenericRelationListField( to={"agenda_item": "tag_ids", "assignment": "tag_ids", "motion": "tag_ids"}, + is_view_field=True, equal_fields="meeting_id", ) meeting_id = fields.RelationField( @@ -1095,14 +1233,15 @@ class AgendaItem(Model, AgendaItemModelMixin): to={"agenda_item": "child_ids"}, equal_fields="meeting_id" ) child_ids = fields.RelationListField( - to={"agenda_item": "parent_id"}, equal_fields="meeting_id" + to={"agenda_item": "parent_id"}, is_view_field=True, equal_fields="meeting_id" ) tag_ids = fields.RelationListField( - to={"tag": "tagged_ids"}, equal_fields="meeting_id" + to={"tag": "tagged_ids"}, is_view_field=True, equal_fields="meeting_id" ) projection_ids = fields.RelationListField( to={"projection": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) meeting_id = fields.RelationField( @@ -1139,16 +1278,19 @@ class ListOfSpeakers(Model): speaker_ids = fields.RelationListField( to={"speaker": "list_of_speakers_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) structure_level_list_of_speakers_ids = fields.RelationListField( to={"structure_level_list_of_speakers": "list_of_speakers_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) projection_ids = fields.RelationListField( to={"projection": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) meeting_id = fields.RelationField( @@ -1172,7 +1314,9 @@ class StructureLevelListOfSpeakers(Model): equal_fields="meeting_id", ) speaker_ids = fields.RelationListField( - to={"speaker": "structure_level_list_of_speakers_id"}, equal_fields="meeting_id" + to={"speaker": "structure_level_list_of_speakers_id"}, + is_view_field=True, + equal_fields="meeting_id", ) initial_time = fields.IntegerField( required=True, @@ -1213,7 +1357,9 @@ class PointOfOrderCategory(Model): to={"meeting": "point_of_order_category_ids"}, required=True, constant=True ) speaker_ids = fields.RelationListField( - to={"speaker": "point_of_order_category_id"}, equal_fields="meeting_id" + to={"speaker": "point_of_order_category_id"}, + is_view_field=True, + equal_fields="meeting_id", ) @@ -1278,7 +1424,9 @@ class Topic(Model): }, ) attachment_ids = fields.RelationListField( - to={"mediafile": "attachment_ids"}, equal_fields="meeting_id" + to={"mediafile": "attachment_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) agenda_item_id = fields.RelationField( to={"agenda_item": "content_object_id"}, @@ -1297,11 +1445,13 @@ class Topic(Model): poll_ids = fields.RelationListField( to={"poll": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) projection_ids = fields.RelationListField( to={"projection": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) meeting_id = fields.RelationField( @@ -1351,21 +1501,30 @@ class Motion(Model): amendment_ids = fields.RelationListField( to={"motion": "lead_motion_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) sort_parent_id = fields.RelationField( to={"motion": "sort_child_ids"}, equal_fields="meeting_id" ) sort_child_ids = fields.RelationListField( - to={"motion": "sort_parent_id"}, equal_fields="meeting_id" + to={"motion": "sort_parent_id"}, is_view_field=True, equal_fields="meeting_id" ) origin_id = fields.RelationField(to={"motion": "derived_motion_ids"}) origin_meeting_id = fields.RelationField(to={"meeting": "forwarded_motion_ids"}) - derived_motion_ids = fields.RelationListField(to={"motion": "origin_id"}) - all_origin_ids = fields.RelationListField(to={"motion": "all_derived_motion_ids"}) - all_derived_motion_ids = fields.RelationListField(to={"motion": "all_origin_ids"}) - identical_motion_ids = fields.RelationListField( - to={"motion": "identical_motion_ids"}, equal_fields="meeting_id" + derived_motion_ids = fields.RelationListField( + to={"motion": "origin_id"}, is_view_field=True + ) + all_origin_ids = fields.RelationListField( + to={"motion": "all_derived_motion_ids"}, is_view_field=True + ) + all_derived_motion_ids = fields.RelationListField( + to={"motion": "all_origin_ids"}, is_view_field=True + ) + identical_motion_ids = fields.NumberArrayField( + constraints={ + "description": "Changed from relation-list to number[], because it still can't be generated" + } ) state_id = fields.RelationField( to={"motion_state": "motion_ids"}, required=True, equal_fields="meeting_id" @@ -1375,17 +1534,22 @@ class Motion(Model): ) state_extension_reference_ids = fields.GenericRelationListField( to={"motion": "referenced_in_motion_state_extension_ids"}, + is_view_field=True, equal_fields="meeting_id", ) referenced_in_motion_state_extension_ids = fields.RelationListField( - to={"motion": "state_extension_reference_ids"}, equal_fields="meeting_id" + to={"motion": "state_extension_reference_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) recommendation_extension_reference_ids = fields.GenericRelationListField( to={"motion": "referenced_in_motion_recommendation_extension_ids"}, + is_view_field=True, equal_fields="meeting_id", ) referenced_in_motion_recommendation_extension_ids = fields.RelationListField( to={"motion": "recommendation_extension_reference_ids"}, + is_view_field=True, equal_fields="meeting_id", ) category_id = fields.RelationField( @@ -1397,34 +1561,42 @@ class Motion(Model): submitter_ids = fields.RelationListField( to={"motion_submitter": "motion_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) supporter_meeting_user_ids = fields.RelationListField( - to={"meeting_user": "supported_motion_ids"}, equal_fields="meeting_id" + to={"meeting_user": "supported_motion_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) editor_ids = fields.RelationListField( to={"motion_editor": "motion_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) working_group_speaker_ids = fields.RelationListField( to={"motion_working_group_speaker": "motion_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) poll_ids = fields.RelationListField( to={"poll": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) option_ids = fields.RelationListField( to={"option": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) change_recommendation_ids = fields.RelationListField( to={"motion_change_recommendation": "motion_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) statute_paragraph_id = fields.RelationField( @@ -1433,6 +1605,7 @@ class Motion(Model): comment_ids = fields.RelationListField( to={"motion_comment": "motion_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) agenda_item_id = fields.RelationField( @@ -1448,19 +1621,23 @@ class Motion(Model): equal_fields="meeting_id", ) tag_ids = fields.RelationListField( - to={"tag": "tagged_ids"}, equal_fields="meeting_id" + to={"tag": "tagged_ids"}, is_view_field=True, equal_fields="meeting_id" ) attachment_ids = fields.RelationListField( - to={"mediafile": "attachment_ids"}, equal_fields="meeting_id" + to={"mediafile": "attachment_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) projection_ids = fields.RelationListField( to={"projection": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) personal_note_ids = fields.RelationListField( to={"personal_note": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) meeting_id = fields.RelationField( @@ -1570,13 +1747,18 @@ class MotionCommentSection(Model): comment_ids = fields.RelationListField( to={"motion_comment": "section_id"}, on_delete=fields.OnDelete.PROTECT, + is_view_field=True, equal_fields="meeting_id", ) read_group_ids = fields.RelationListField( - to={"group": "read_comment_section_ids"}, equal_fields="meeting_id" + to={"group": "read_comment_section_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) write_group_ids = fields.RelationListField( - to={"group": "write_comment_section_ids"}, equal_fields="meeting_id" + to={"group": "write_comment_section_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) meeting_id = fields.RelationField( to={"meeting": "motion_comment_section_ids"}, required=True, constant=True @@ -1606,10 +1788,12 @@ class MotionCategory(Model): to={"motion_category": "child_ids"}, equal_fields="meeting_id" ) child_ids = fields.RelationListField( - to={"motion_category": "parent_id"}, equal_fields="meeting_id" + to={"motion_category": "parent_id"}, + is_view_field=True, + equal_fields="meeting_id", ) motion_ids = fields.RelationListField( - to={"motion": "category_id"}, equal_fields="meeting_id" + to={"motion": "category_id"}, is_view_field=True, equal_fields="meeting_id" ) meeting_id = fields.RelationField( to={"meeting": "motion_category_ids"}, required=True, constant=True @@ -1632,7 +1816,7 @@ class MotionBlock(Model): }, ) motion_ids = fields.RelationListField( - to={"motion": "block_id"}, equal_fields="meeting_id" + to={"motion": "block_id"}, is_view_field=True, equal_fields="meeting_id" ) agenda_item_id = fields.RelationField( to={"agenda_item": "content_object_id"}, @@ -1648,6 +1832,7 @@ class MotionBlock(Model): projection_ids = fields.RelationListField( to={"projection": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) meeting_id = fields.RelationField( @@ -1725,23 +1910,29 @@ class MotionState(Model): ) submitter_withdraw_back_ids = fields.RelationListField( to={"motion_state": "submitter_withdraw_state_id"}, + is_view_field=True, equal_fields=["meeting_id", "workflow_id"], ) next_state_ids = fields.RelationListField( to={"motion_state": "previous_state_ids"}, + is_view_field=True, equal_fields=["meeting_id", "workflow_id"], ) previous_state_ids = fields.RelationListField( to={"motion_state": "next_state_ids"}, + is_view_field=True, equal_fields=["meeting_id", "workflow_id"], ) motion_ids = fields.RelationListField( to={"motion": "state_id"}, on_delete=fields.OnDelete.PROTECT, + is_view_field=True, equal_fields="meeting_id", ) motion_recommendation_ids = fields.RelationListField( - to={"motion": "recommendation_id"}, equal_fields="meeting_id" + to={"motion": "recommendation_id"}, + is_view_field=True, + equal_fields="meeting_id", ) workflow_id = fields.RelationField( to={"motion_workflow": "state_ids"}, required=True, equal_fields="meeting_id" @@ -1773,6 +1964,7 @@ class MotionWorkflow(Model): state_ids = fields.RelationListField( to={"motion_state": "workflow_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) first_state_id = fields.RelationField( @@ -1811,7 +2003,9 @@ class MotionStatuteParagraph(Model): }, ) motion_ids = fields.RelationListField( - to={"motion": "statute_paragraph_id"}, equal_fields="meeting_id" + to={"motion": "statute_paragraph_id"}, + is_view_field=True, + equal_fields="meeting_id", ) meeting_id = fields.RelationField( to={"meeting": "motion_statute_paragraph_ids"}, required=True, constant=True @@ -1899,6 +2093,7 @@ class Poll(Model, PollModelMixin): option_ids = fields.RelationListField( to={"option": "poll_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) global_option_id = fields.RelationField( @@ -1907,13 +2102,16 @@ class Poll(Model, PollModelMixin): constant=True, equal_fields="meeting_id", ) - voted_ids = fields.RelationListField(to={"user": "poll_voted_ids"}) + voted_ids = fields.RelationListField( + to={"user": "poll_voted_ids"}, is_view_field=True + ) entitled_group_ids = fields.RelationListField( - to={"group": "poll_ids"}, equal_fields="meeting_id" + to={"group": "poll_ids"}, is_view_field=True, equal_fields="meeting_id" ) projection_ids = fields.RelationListField( to={"projection": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) meeting_id = fields.RelationField( @@ -1940,6 +2138,7 @@ class Option(Model): vote_ids = fields.RelationListField( to={"vote": "option_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) content_object_id = fields.GenericRelationField( @@ -2001,11 +2200,13 @@ class Assignment(Model): candidate_ids = fields.RelationListField( to={"assignment_candidate": "assignment_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) poll_ids = fields.RelationListField( to={"poll": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) agenda_item_id = fields.RelationField( @@ -2021,14 +2222,17 @@ class Assignment(Model): equal_fields="meeting_id", ) tag_ids = fields.RelationListField( - to={"tag": "tagged_ids"}, equal_fields="meeting_id" + to={"tag": "tagged_ids"}, is_view_field=True, equal_fields="meeting_id" ) attachment_ids = fields.RelationListField( - to={"mediafile": "attachment_ids"}, equal_fields="meeting_id" + to={"mediafile": "attachment_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) projection_ids = fields.RelationListField( to={"projection": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) meeting_id = fields.RelationField( @@ -2064,6 +2268,7 @@ class PollCandidateList(Model): poll_candidate_ids = fields.RelationListField( to={"poll_candidate": "poll_candidate_list_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) meeting_id = fields.RelationField( @@ -2126,30 +2331,34 @@ class Mediafile(Model): token = fields.CharField() inherited_access_group_ids = fields.RelationListField( to={"group": "mediafile_inherited_access_group_ids"}, + is_view_field=True, read_only=True, constraints={"description": "Calculated field."}, ) access_group_ids = fields.RelationListField( - to={"group": "mediafile_access_group_ids"} + to={"group": "mediafile_access_group_ids"}, is_view_field=True ) parent_id = fields.RelationField( to={"mediafile": "child_ids"}, equal_fields="owner_id" ) child_ids = fields.RelationListField( - to={"mediafile": "parent_id"}, equal_fields="owner_id" + to={"mediafile": "parent_id"}, is_view_field=True, equal_fields="owner_id" ) list_of_speakers_id = fields.RelationField( to={"list_of_speakers": "content_object_id"}, on_delete=fields.OnDelete.CASCADE ) projection_ids = fields.RelationListField( - to={"projection": "content_object_id"}, on_delete=fields.OnDelete.CASCADE + to={"projection": "content_object_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, ) attachment_ids = fields.GenericRelationListField( to={ "motion": "attachment_ids", "topic": "attachment_ids", "assignment": "attachment_ids", - } + }, + is_view_field=True, ) owner_id = fields.GenericRelationField( to={"organization": "mediafile_ids", "meeting": "mediafile_ids"}, @@ -2242,16 +2451,19 @@ class Projector(Model): current_projection_ids = fields.RelationListField( to={"projection": "current_projector_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) preview_projection_ids = fields.RelationListField( to={"projection": "preview_projector_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) history_projection_ids = fields.RelationListField( to={"projection": "history_projector_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) used_as_reference_projector_meeting_id = fields.RelationField( @@ -2266,10 +2478,8 @@ class Projector(Model): used_as_default_projector_for_list_of_speakers_in_meeting_id = fields.RelationField( to={"meeting": "default_projector_list_of_speakers_ids"} ) - used_as_default_projector_for_current_list_of_speakers_in_meeting_id = ( - fields.RelationField( - to={"meeting": "default_projector_current_list_of_speakers_ids"} - ) + used_as_default_projector_for_current_los_in_meeting_id = fields.RelationField( + to={"meeting": "default_projector_current_los_ids"} ) used_as_default_projector_for_motion_in_meeting_id = fields.RelationField( to={"meeting": "default_projector_motion_ids"} @@ -2356,6 +2566,7 @@ class ProjectorMessage(Model): projection_ids = fields.RelationListField( to={"projection": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) meeting_id = fields.RelationField( @@ -2376,6 +2587,7 @@ class ProjectorCountdown(Model): projection_ids = fields.RelationListField( to={"projection": "content_object_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) used_as_list_of_speakers_countdown_meeting_id = fields.RelationField( @@ -2399,13 +2611,18 @@ class ChatGroup(Model): chat_message_ids = fields.RelationListField( to={"chat_message": "chat_group_id"}, on_delete=fields.OnDelete.CASCADE, + is_view_field=True, equal_fields="meeting_id", ) read_group_ids = fields.RelationListField( - to={"group": "read_chat_group_ids"}, equal_fields="meeting_id" + to={"group": "read_chat_group_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) write_group_ids = fields.RelationListField( - to={"group": "write_chat_group_ids"}, equal_fields="meeting_id" + to={"group": "write_chat_group_ids"}, + is_view_field=True, + equal_fields="meeting_id", ) meeting_id = fields.RelationField( to={"meeting": "chat_group_ids"}, required=True, constant=True From f240616f0beb4c9a88696f2ee3fb4d45d94bc8c0 Mon Sep 17 00:00:00 2001 From: Joshua Sangmeister Date: Thu, 18 Apr 2024 10:46:26 +0200 Subject: [PATCH 2/9] Update meta & fix model generation --- cli/generate_models.py | 4 +--- global/meta | 2 +- openslides_backend/models/models.py | 22 ++++++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cli/generate_models.py b/cli/generate_models.py index 6c33a7880..9ee8dcb2d 100644 --- a/cli/generate_models.py +++ b/cli/generate_models.py @@ -220,9 +220,7 @@ def __init__(self, value: str | dict) -> None: if self.type in RELATION_FIELD_CLASSES.keys(): self.to = To(value.pop("to")) self.on_delete = value.pop("on_delete", None) - if self.type in ("relation-list", "generic-relation-list") or value.get( - "sql" - ): + if self.type.endswith("relation-list") or value.get("sql") or (value.get("to") and not value.get("reference")): self.is_view_field = True else: assert self.type in COMMON_FIELD_CLASSES.keys(), ( diff --git a/global/meta b/global/meta index c85ac7c24..7203c19eb 160000 --- a/global/meta +++ b/global/meta @@ -1 +1 @@ -Subproject commit c85ac7c24741ba2ae9f7d1fdf8abb36c37ed2333 +Subproject commit 7203c19ebfa48d5c88c54fb37b16a725183ddc80 diff --git a/openslides_backend/models/models.py b/openslides_backend/models/models.py index 12ae5423d..e3fbae3b9 100644 --- a/openslides_backend/models/models.py +++ b/openslides_backend/models/models.py @@ -118,11 +118,12 @@ class User(Model): is_present_in_meeting_ids = fields.RelationListField( to={"meeting": "present_user_ids"}, is_view_field=True ) - committee_ids = fields.NumberArrayField( + committee_ids = fields.RelationListField( + to={"committee": "user_ids"}, + is_view_field=True, read_only=True, constraints={ - "to": "committee/user_ids", - "description": "Calculated field: Returns committee_ids, where the user is manager or member in a meeting", + "description": "Calculated field: Returns committee_ids, where the user is manager or member in a meeting" }, ) committee_management_ids = fields.RelationListField( @@ -323,11 +324,12 @@ class Committee(Model): default_meeting_id = fields.RelationField( to={"meeting": "default_meeting_for_committee_id"} ) - user_ids = fields.NumberArrayField( + user_ids = fields.RelationListField( + to={"user": "committee_ids"}, + is_view_field=True, read_only=True, constraints={ - "to": "user/committee_ids", - "description": "Calculated field: All users which are in a group of a meeting, belonging to the committee or beeing manager of the committee", + "description": "Calculated field: All users which are in a group of a meeting, belonging to the committee or beeing manager of the committee" }, ) manager_ids = fields.RelationListField( @@ -417,7 +419,7 @@ class Meeting(Model, MeetingModelMixin): export_pdf_pagenumber_alignment = fields.CharField( default="center", constraints={"enum": ["left", "right", "center"]} ) - export_pdf_fontsize = fields.CharField( + export_pdf_fontsize = fields.IntegerField( default=10, constraints={"enum": [10, 11, 12]} ) export_pdf_line_height = fields.FloatField( @@ -876,10 +878,10 @@ class Meeting(Model, MeetingModelMixin): to={"mediafile": "used_as_logo_pdf_header_r_in_meeting_id"} ) logo_pdf_footer_l_id = fields.RelationField( - to={"mediafile": "used_as_logo_pdf_header_l_in_meeting_id"} + to={"mediafile": "used_as_logo_pdf_footer_l_in_meeting_id"} ) logo_pdf_footer_r_id = fields.RelationField( - to={"mediafile": "used_as_logo_pdf_header_l_in_meeting_id"} + to={"mediafile": "used_as_logo_pdf_footer_r_in_meeting_id"} ) logo_pdf_ballot_paper_id = fields.RelationField( to={"mediafile": "used_as_logo_pdf_ballot_paper_in_meeting_id"} @@ -1523,7 +1525,7 @@ class Motion(Model): ) identical_motion_ids = fields.NumberArrayField( constraints={ - "description": "Changed from relation-list to number[], because it still can't be generated" + "description": "with psycopg 3.2.0 we could use the as_string method without cursor and change dummy to number. Changed from relation-list to number[], because it still can''t be generated." } ) state_id = fields.RelationField( From b9a58430c783a556c305af76452c702b05b2ece0 Mon Sep 17 00:00:00 2001 From: Joshua Sangmeister Date: Thu, 18 Apr 2024 11:01:33 +0200 Subject: [PATCH 3/9] Fix formatting --- cli/generate_models.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/generate_models.py b/cli/generate_models.py index 9ee8dcb2d..7b48fc2c7 100644 --- a/cli/generate_models.py +++ b/cli/generate_models.py @@ -220,7 +220,11 @@ def __init__(self, value: str | dict) -> None: if self.type in RELATION_FIELD_CLASSES.keys(): self.to = To(value.pop("to")) self.on_delete = value.pop("on_delete", None) - if self.type.endswith("relation-list") or value.get("sql") or (value.get("to") and not value.get("reference")): + if ( + self.type.endswith("relation-list") + or value.get("sql") + or (value.get("to") and not value.get("reference")) + ): self.is_view_field = True else: assert self.type in COMMON_FIELD_CLASSES.keys(), ( From 53ede5ac56d2b16a6059815c3e0e3b3bddb18074 Mon Sep 17 00:00:00 2001 From: Joshua Sangmeister Date: Thu, 18 Apr 2024 11:02:56 +0200 Subject: [PATCH 4/9] Re-enable CI --- .github/workflows/continuous_integration.yml | 6 +++--- global/meta | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml index e9377ff15..85339ebff 100644 --- a/.github/workflows/continuous_integration.yml +++ b/.github/workflows/continuous_integration.yml @@ -153,9 +153,9 @@ jobs: - name: Install requirements run: . requirements/export_service_commits.sh && pip install --requirement requirements/requirements_development.txt - # - name: Check for up to date models.py - # if: always() - # run: make check-models + - name: Check for up to date models.py + if: always() + run: make check-models - name: Check for up to date permissions.py if: always() diff --git a/global/meta b/global/meta index 7203c19eb..ba658f876 160000 --- a/global/meta +++ b/global/meta @@ -1 +1 @@ -Subproject commit 7203c19ebfa48d5c88c54fb37b16a725183ddc80 +Subproject commit ba658f8768baa025c7373868024ee5406eba751c From 091402a228b3f6a982c476f3c286010f3fe1abe0 Mon Sep 17 00:00:00 2001 From: Joshua Sangmeister Date: Thu, 18 Apr 2024 15:43:03 +0200 Subject: [PATCH 5/9] Update meta --- global/meta | 2 +- openslides_backend/models/models.py | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/global/meta b/global/meta index ba658f876..9cef28fa9 160000 --- a/global/meta +++ b/global/meta @@ -1 +1 @@ -Subproject commit ba658f8768baa025c7373868024ee5406eba751c +Subproject commit 9cef28fa9cd9f0b637b1c580a8ce218d296ed2c0 diff --git a/openslides_backend/models/models.py b/openslides_backend/models/models.py index e3fbae3b9..8718c3495 100644 --- a/openslides_backend/models/models.py +++ b/openslides_backend/models/models.py @@ -150,7 +150,9 @@ class User(Model): poll_candidate_ids = fields.RelationListField( to={"poll_candidate": "user_id"}, is_view_field=True ) - meeting_ids = fields.NumberArrayField( + meeting_ids = fields.RelationListField( + to={"meeting": "user_ids"}, + is_view_field=True, read_only=True, constraints={ "description": "Calculated. All ids from meetings calculated via meeting_user and group_ids as integers." @@ -922,7 +924,9 @@ class Meeting(Model, MeetingModelMixin): present_user_ids = fields.RelationListField( to={"user": "is_present_in_meeting_ids"}, is_view_field=True ) - user_ids = fields.NumberArrayField( + user_ids = fields.RelationListField( + to={"user": "meeting_ids"}, + is_view_field=True, read_only=True, constraints={ "description": "Calculated. All user ids from all users assigned to groups of this meeting." From 7625e32cbc00d8f84833acae3b7023b20920d5fa Mon Sep 17 00:00:00 2001 From: Joshua Sangmeister Date: Thu, 18 Apr 2024 15:45:55 +0200 Subject: [PATCH 6/9] Update meta --- global/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global/meta b/global/meta index 9cef28fa9..e50987844 160000 --- a/global/meta +++ b/global/meta @@ -1 +1 @@ -Subproject commit 9cef28fa9cd9f0b637b1c580a8ce218d296ed2c0 +Subproject commit e509878445111592aabf600ca8fd0753218289f2 From 62c2bb4d5016ac8a68c9326b58ddd0e1271ce11f Mon Sep 17 00:00:00 2001 From: Joshua Sangmeister Date: Thu, 18 Apr 2024 16:05:25 +0200 Subject: [PATCH 7/9] Revert relation change --- global/meta | 2 +- openslides_backend/models/models.py | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/global/meta b/global/meta index e50987844..98307c579 160000 --- a/global/meta +++ b/global/meta @@ -1 +1 @@ -Subproject commit e509878445111592aabf600ca8fd0753218289f2 +Subproject commit 98307c57978810c411d3310c6b33a3379c1082ec diff --git a/openslides_backend/models/models.py b/openslides_backend/models/models.py index 8718c3495..e3fbae3b9 100644 --- a/openslides_backend/models/models.py +++ b/openslides_backend/models/models.py @@ -150,9 +150,7 @@ class User(Model): poll_candidate_ids = fields.RelationListField( to={"poll_candidate": "user_id"}, is_view_field=True ) - meeting_ids = fields.RelationListField( - to={"meeting": "user_ids"}, - is_view_field=True, + meeting_ids = fields.NumberArrayField( read_only=True, constraints={ "description": "Calculated. All ids from meetings calculated via meeting_user and group_ids as integers." @@ -924,9 +922,7 @@ class Meeting(Model, MeetingModelMixin): present_user_ids = fields.RelationListField( to={"user": "is_present_in_meeting_ids"}, is_view_field=True ) - user_ids = fields.RelationListField( - to={"user": "meeting_ids"}, - is_view_field=True, + user_ids = fields.NumberArrayField( read_only=True, constraints={ "description": "Calculated. All user ids from all users assigned to groups of this meeting." From 717fe51ac92a0831b4ec0f1f91b319389016f203 Mon Sep 17 00:00:00 2001 From: Joshua Sangmeister Date: Fri, 19 Apr 2024 08:50:11 +0200 Subject: [PATCH 8/9] Update models --- global/meta | 2 +- openslides_backend/models/models.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/global/meta b/global/meta index 98307c579..b6da76d3b 160000 --- a/global/meta +++ b/global/meta @@ -1 +1 @@ -Subproject commit 98307c57978810c411d3310c6b33a3379c1082ec +Subproject commit b6da76d3b578d4f89740b28c374be5d44c12c10d diff --git a/openslides_backend/models/models.py b/openslides_backend/models/models.py index e3fbae3b9..1c8434901 100644 --- a/openslides_backend/models/models.py +++ b/openslides_backend/models/models.py @@ -1523,10 +1523,8 @@ class Motion(Model): all_derived_motion_ids = fields.RelationListField( to={"motion": "all_origin_ids"}, is_view_field=True ) - identical_motion_ids = fields.NumberArrayField( - constraints={ - "description": "with psycopg 3.2.0 we could use the as_string method without cursor and change dummy to number. Changed from relation-list to number[], because it still can''t be generated." - } + identical_motion_ids = fields.RelationListField( + to={"motion": "identical_motion_ids"}, is_view_field=True ) state_id = fields.RelationField( to={"motion_state": "motion_ids"}, required=True, equal_fields="meeting_id" From 2f4620acb5cf5369074a42cd38ef0d4dd0c1225d Mon Sep 17 00:00:00 2001 From: Joshua Sangmeister Date: Fri, 19 Apr 2024 09:17:41 +0200 Subject: [PATCH 9/9] Update meta --- global/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global/meta b/global/meta index b6da76d3b..33f340d93 160000 --- a/global/meta +++ b/global/meta @@ -1 +1 @@ -Subproject commit b6da76d3b578d4f89740b28c374be5d44c12c10d +Subproject commit 33f340d93fb791427b7ec353f8c2670819a48ec5