@@ -70,34 +70,42 @@ def create_entity_list() -> EntityList:
7070 return EntityList .objects .create ()
7171
7272
73- def create_entity_list_row (
73+ def create_entity_list_rows (
7474 entity_list : EntityList ,
75- entity_pk : int ,
76- order_num : int ,
77- draft_version_pk : int | None ,
78- published_version_pk : int | None ,
75+ entity_pks : list [int ],
76+ draft_version_pks : list [int | None ],
77+ published_version_pks : list [int | None ],
7978) -> EntityListRow :
8079 """
81- Create a new entity list row. This is a row in an entity list that references
82- publishable entities.
80+ Create new entity list rows for an entity list.
8381
8482 Args:
85- entity_list: The entity list that the entity list row belongs to.
86- entity: The ID of the publishable entity that the entity list row references.
87- order_num: The order_num of the entity list row in the entity list.
88- draft_version_pk: The ID of the draft version of the entity (PublishableEntityVersion) that the entity list row references.
89- published_version_pk: The ID of the published version of the entity (PublishableEntityVersion) that the entity list row references
83+ entity_list: The entity list to create the rows for.
84+ entity_pks: The IDs of the publishable entities that the entity list rows reference.
85+ draft_version_pks: The IDs of the draft versions of the entities (PublishableEntityVersion) that the entity list rows reference.
86+ published_version_pks: The IDs of the published versions of the entities (PublishableEntityVersion) that the entity list rows reference.
9087
9188 Returns:
92- The newly created entity list row .
89+ The newly created entity list rows .
9390 """
94- return EntityListRow .objects .create (
95- entity_list = entity_list ,
96- entity_id = entity_pk ,
97- order_num = order_num ,
98- draft_version_id = draft_version_pk ,
99- published_version_id = published_version_pk ,
100- )
91+ order_nums = range (len (entity_pks ))
92+ with atomic ():
93+ entity_list_rows = EntityListRow .objects .bulk_create (
94+ [
95+ EntityListRow (
96+ entity_list = entity_list ,
97+ entity_id = entity_pk ,
98+ order_num = order_num ,
99+ draft_version_id = draft_version_pk ,
100+ published_version_id = published_version_pk ,
101+ )
102+ for entity_pk , order_num , draft_version_pk , published_version_pk in zip (
103+ entity_pks , order_nums , draft_version_pks , published_version_pks
104+ )
105+ ]
106+ )
107+
108+ return entity_list_rows
101109
102110
103111def create_entity_list_with_rows (
@@ -109,26 +117,55 @@ def create_entity_list_with_rows(
109117 Create a new entity list with rows.
110118
111119 Args:
112- entity_pks: The IDs of the publishable entities that the entity list rows reference.
120+ entity_pks: The IDs of the publishable entities that the entity list rows
121+ reference.
113122 order_nums: The order_nums of the entity list rows in the entity list.
114- draft_version_pks: The IDs of the draft versions of the entities (PublishableEntityVersion) that the entity list rows reference.
115- published_version_pks: The IDs of the published versions of the entities (PublishableEntityVersion) that the entity list rows reference.
123+ draft_version_pks: The IDs of the draft versions of the entities
124+ (PublishableEntityVersion) that the entity list rows reference.
125+ published_version_pks: The IDs of the published versions of the entities
126+ (PublishableEntityVersion) that the entity list rows reference.
116127
117128 Returns:
118129 The newly created entity list.
119130 """
120131 entity_list = create_entity_list ()
121- order_nums = range (len (entity_pks ))
122- for entity_pk , order_num , draft_version_pk , published_version_pk in zip (
123- entity_pks , order_nums , draft_version_pks , published_version_pks
124- ):
125- create_entity_list_row (
126- entity_list = entity_list ,
127- entity_pk = entity_pk ,
128- order_num = order_num ,
129- draft_version_pk = draft_version_pk ,
130- published_version_pk = published_version_pk ,
132+ create_entity_list_rows (
133+ entity_list = entity_list ,
134+ entity_pks = entity_pks ,
135+ draft_version_pks = draft_version_pks ,
136+ published_version_pks = published_version_pks ,
137+ )
138+ return entity_list
139+
140+
141+ def copy_rows_to_new_entity_list (
142+ rows : QuerySet [EntityListRow ],
143+ ) -> EntityList :
144+ """
145+ Copy rows from an existing entity list to a new entity list.
146+
147+ Args:
148+ entity_list: The entity list to copy the rows to.
149+ rows: The rows to copy to the new entity list.
150+
151+ Returns:
152+ The newly created entity list.
153+ """
154+ entity_list = create_entity_list ()
155+ with atomic ():
156+ entity_list_rows = EntityListRow .objects .bulk_create (
157+ [
158+ EntityListRow (
159+ entity_list = entity_list ,
160+ entity_id = row .entity .id ,
161+ order_num = row .order_num ,
162+ draft_version_id = row .entity .draft .version .pk ,
163+ published_version_id = row .entity .published .version .pk ,
164+ )
165+ for row in rows
166+ ]
131167 )
168+
132169 return entity_list
133170
134171
@@ -137,6 +174,8 @@ def create_container_version(
137174 version_num : int ,
138175 title : str ,
139176 publishable_entities_pk : list [int ],
177+ draft_version_pks : list [int | None ],
178+ published_version_pks : list [int | None ],
140179 entity : PublishableEntity ,
141180 created : datetime ,
142181 created_by : int | None ,
@@ -164,20 +203,17 @@ def create_container_version(
164203 created = created ,
165204 created_by = created_by ,
166205 )
167- # This implementation assumes:
168- # 1. We are creating the first version of the container, so the defined list is the same as the initial list.
169- # 2. The frozen list is empty because this is the first version.
170- # 3. Published and draft versions are always the latest for all members.
171206 entity_list = create_entity_list_with_rows (
172207 entity_pks = publishable_entities_pk ,
173- draft_version_pks = [ None ] * len ( publishable_entities_pk ) ,
174- published_version_pks = [ None ] * len ( publishable_entities_pk ) ,
208+ draft_version_pks = draft_version_pks ,
209+ published_version_pks = published_version_pks ,
175210 )
176211 container_version = ContainerEntityVersion .objects .create (
177212 publishable_entity_version = publishable_entity_version ,
178213 container_id = container_pk ,
179214 defined_list = entity_list ,
180215 initial_list = entity_list ,
216+ # Would frozen_list be always None the 1st time a container is created?
181217 frozen_list = None ,
182218 )
183219 return container_version
@@ -187,6 +223,8 @@ def create_next_container_version(
187223 container_pk : int ,
188224 title : str ,
189225 publishable_entities_pk : list [int ],
226+ draft_version_pks : list [int | None ],
227+ published_version_pks : list [int | None ],
190228 entity : PublishableEntity ,
191229 created : datetime ,
192230 created_by : int | None ,
@@ -216,23 +254,26 @@ def create_next_container_version(
216254 created = created ,
217255 created_by = created_by ,
218256 )
219- # This implementation assumes:
220- # 1. The changes provoking a new version are the addition, removal of members or reordering.
257+ # 1. The changes provoking a new version are always the addition, removal of members or reordering. How can we detect changes only in the metadata?
221258 # 2. Published and draft versions are always the latest for all members.
222259 # 3. When creating a new version, a new user-defined entity list is created to preserve the latest state as the previous user-defined list.
223- # TODO: instead consider copying the previous user-defined list as the frozen list, and add/remove to the previous user-defined list.
224- # If it's a reordering, the previous user-defined list is copied as the frozen and a new user-defined list is created with the new order .
260+ # 4. When creating a new version, a new frozen entity list is created copying the state of the user-defined list of the previous version .
261+ # 5. While copying the versions into the new frozen list, versions are pinned in new rows for published/draft versions .
225262 new_user_defined_list = create_entity_list_with_rows (
226263 entity_pks = publishable_entities_pk ,
227- draft_version_pks = [ None ] * len ( publishable_entities_pk ) ,
228- published_version_pks = [ None ] * len ( publishable_entities_pk ) ,
264+ draft_version_pks = draft_version_pks ,
265+ published_version_pks = published_version_pks ,
229266 )
267+ new_frozen_list = copy_rows_to_new_entity_list (
268+ rows = get_defined_list_rows_for_container_version (last_version )
269+ )
270+
230271 container_version = ContainerEntityVersion .objects .create (
231272 publishable_entity_version = publishable_entity_version ,
232273 container_id = container_pk ,
233274 defined_list = new_user_defined_list ,
234275 initial_list = last_version .initial_list ,
235- frozen_list = last_version . defined_list ,
276+ frozen_list = new_frozen_list ,
236277 )
237278 return container_version
238279
@@ -244,6 +285,8 @@ def create_container_and_version(
244285 created_by : int | None ,
245286 title : str ,
246287 publishable_entities_pk : list [int ],
288+ draft_version_pks : list [int | None ],
289+ published_version_pks : list [int | None ],
247290) -> ContainerEntityVersion :
248291 """
249292 Create a new container and its first version.
@@ -267,6 +310,8 @@ def create_container_and_version(
267310 version_num = 1 ,
268311 title = title ,
269312 publishable_entities_pk = publishable_entities_pk ,
313+ draft_version_pks = draft_version_pks ,
314+ published_version_pks = published_version_pks ,
270315 entity = container .publishable_entity ,
271316 created = created ,
272317 created_by = created_by ,
@@ -283,13 +328,12 @@ def get_container(pk: int) -> ContainerEntity:
283328
284329 Returns:
285330 The container with the given primary key.
286-
287- TODO: should this use with_publishing_relations as in components?
288331 """
332+ # TODO: should this use with_publishing_relations as in components?
289333 return ContainerEntity .objects .get (pk = pk )
290334
291335
292- def get_defined_list_for_container_version (
336+ def get_defined_list_rows_for_container_version (
293337 container_version : ContainerEntityVersion ,
294338) -> QuerySet [EntityListRow ]:
295339 """
@@ -304,7 +348,7 @@ def get_defined_list_for_container_version(
304348 return container_version .defined_list .entitylistrow_set .all ()
305349
306350
307- def get_initial_list_for_container_version (
351+ def get_initial_list_rows_for_container_version (
308352 container_version : ContainerEntityVersion ,
309353) -> QuerySet [EntityListRow ]:
310354 """
@@ -319,7 +363,7 @@ def get_initial_list_for_container_version(
319363 return container_version .initial_list .entitylistrow_set .all ()
320364
321365
322- def get_frozen_list_for_container_version (
366+ def get_frozen_list_rows_for_container_version (
323367 container_version : ContainerEntityVersion ,
324368) -> QuerySet [EntityListRow ]:
325369 """
@@ -331,4 +375,6 @@ def get_frozen_list_for_container_version(
331375 Returns:
332376 The frozen members of the container version.
333377 """
378+ if container_version .frozen_list is None :
379+ return QuerySet [EntityListRow ]()
334380 return container_version .frozen_list .entitylistrow_set .all ()
0 commit comments