1717from django .db .models import Case , When
1818from django .core .exceptions import ValidationError
1919
20+ from .exceptions import NodeNotReachableException
21+ from .transformations import *
22+
2023LIMITING_FK_EDGES_CLAUSE_1 = (
2124 """AND second.{fk_field_name}_{pk_name} = %(limiting_fk_edges_instance_pk)s"""
2225)
189192"""
190193
191194
192- class NodeNotReachableException (Exception ):
193- """
194- Exception for node distance and path
195- """
196-
197- pass
198-
199-
200- def _filter_order (queryset , field_names , values ):
201- """
202- Filters the provided queryset for 'field_name__in values' for each given field_name in [field_names]
203- orders results in the same order as provided values
204-
205- For instance
206- _filter_order(self.__class__.objects, "pk", pks)
207- returns a queryset of the current class, with instances where the 'pk' field matches an pk in pks
208-
209- """
210- if not isinstance (field_names , list ):
211- field_names = [field_names ]
212- case = []
213- for pos , value in enumerate (values ):
214- when_condition = {field_names [0 ]: value , "then" : pos }
215- case .append (When (** when_condition ))
216- order_by = Case (* case )
217- filter_condition = {field_name + "__in" : values for field_name in field_names }
218- return queryset .filter (** filter_condition ).order_by (order_by )
219-
220-
221195def node_factory (edge_model , children_null = True , base_model = models .Model ):
222196 edge_model_table = edge_model ._meta .db_table
223197
@@ -258,7 +232,7 @@ def remove_child(self, child, delete_node=False):
258232 if delete_node :
259233 # Note: Per django docs:
260234 # https://docs.djangoproject.com/en/dev/ref/models/instances/#deleting-objects
261- # This only deletes the object in the database; the Python instance will still
235+ # This only deletes the object in the database; the Python instance will still
262236 # exist and will still have data in its fields.
263237 child .delete ()
264238
@@ -272,7 +246,7 @@ def remove_parent(self, parent, delete_node=False):
272246 if delete_node :
273247 # Note: Per django docs:
274248 # https://docs.djangoproject.com/en/dev/ref/models/instances/#deleting-objects
275- # This only deletes the object in the database; the Python instance will still
249+ # This only deletes the object in the database; the Python instance will still
276250 # exist and will still have data in its fields.
277251 parent .delete ()
278252
@@ -281,7 +255,7 @@ def filter_order_pks(self, pks):
281255 Generates a queryset, based on the current class and the provided pks
282256 """
283257 return _filter_order (self .__class__ .objects , "pk" , pks )
284-
258+
285259 def get_pk_name (self ):
286260 """Sometimes we set a field other than 'pk' for the primary key.
287261 This method is used to get the correct primary key field name for the
@@ -310,12 +284,12 @@ def ancestors_raw(self, max_depth=20, **kwargs):
310284 if fk_field_name is not None :
311285 ancestors_clauses_1 += "\n " + LIMITING_FK_EDGES_CLAUSE_1 .format (
312286 relationship_table = edge_model_table ,
313- pk_name = self .get_pk_name (),
287+ pk_name = self .get_pk_name (),
314288 fk_field_name = fk_field_name ,
315289 )
316290 ancestors_clauses_2 += "\n " + LIMITING_FK_EDGES_CLAUSE_2 .format (
317291 relationship_table = edge_model_table ,
318- pk_name = self .get_pk_name (),
292+ pk_name = self .get_pk_name (),
319293 fk_field_name = fk_field_name ,
320294 )
321295 query_parameters [
@@ -324,13 +298,19 @@ def ancestors_raw(self, max_depth=20, **kwargs):
324298
325299 # Nodes that MUST NOT be included in the results
326300 if disallowed_nodes_queryset is not None :
327- ancestors_clauses_1 += "\n " + DISALLOWED_ANCESTORS_NODES_CLAUSE_1 .format (
328- relationship_table = edge_model_table ,
329- pk_name = self .get_pk_name (),
301+ ancestors_clauses_1 += (
302+ "\n "
303+ + DISALLOWED_ANCESTORS_NODES_CLAUSE_1 .format (
304+ relationship_table = edge_model_table ,
305+ pk_name = self .get_pk_name (),
306+ )
330307 )
331- ancestors_clauses_2 += "\n " + DISALLOWED_ANCESTORS_NODES_CLAUSE_2 .format (
332- relationship_table = edge_model_table ,
333- pk_name = self .get_pk_name (),
308+ ancestors_clauses_2 += (
309+ "\n "
310+ + DISALLOWED_ANCESTORS_NODES_CLAUSE_2 .format (
311+ relationship_table = edge_model_table ,
312+ pk_name = self .get_pk_name (),
313+ )
334314 )
335315 query_parameters ["disallowed_ancestors_node_pks" ] = str (
336316 set (disallowed_nodes_queryset .values_list ("pk" , flat = True ))
@@ -357,6 +337,8 @@ def ancestors_raw(self, max_depth=20, **kwargs):
357337 pass # Not implemented yet
358338
359339 NodeModel = self ._meta .model
340+ print (ancestors_clauses_1 )
341+ print (ancestors_clauses_2 )
360342 raw_qs = NodeModel .objects .raw (
361343 ANCESTORS_QUERY .format (
362344 relationship_table = edge_model_table ,
@@ -366,6 +348,7 @@ def ancestors_raw(self, max_depth=20, **kwargs):
366348 ),
367349 query_parameters ,
368350 )
351+ print (query_parameters )
369352 return raw_qs
370353
371354 def ancestors (self , ** kwargs ):
@@ -406,12 +389,12 @@ def descendants_raw(self, max_depth=20, **kwargs):
406389 if fk_field_name is not None :
407390 descendants_clauses_1 += "\n " + LIMITING_FK_EDGES_CLAUSE_1 .format (
408391 relationship_table = edge_model_table ,
409- pk_name = self .get_pk_name (),
392+ pk_name = self .get_pk_name (),
410393 fk_field_name = fk_field_name ,
411394 )
412395 descendants_clauses_2 += "\n " + LIMITING_FK_EDGES_CLAUSE_2 .format (
413396 relationship_table = edge_model_table ,
414- pk_name = self .get_pk_name (),
397+ pk_name = self .get_pk_name (),
415398 fk_field_name = fk_field_name ,
416399 )
417400 query_parameters [
@@ -420,13 +403,19 @@ def descendants_raw(self, max_depth=20, **kwargs):
420403
421404 # Nodes that MUST NOT be included in the results
422405 if disallowed_nodes_queryset is not None :
423- descendants_clauses_1 += "\n " + DISALLOWED_DESCENDANTS_NODES_CLAUSE_1 .format (
424- relationship_table = edge_model_table ,
425- pk_name = self .get_pk_name (),
406+ descendants_clauses_1 += (
407+ "\n "
408+ + DISALLOWED_DESCENDANTS_NODES_CLAUSE_1 .format (
409+ relationship_table = edge_model_table ,
410+ pk_name = self .get_pk_name (),
411+ )
426412 )
427- descendants_clauses_2 += "\n " + DISALLOWED_DESCENDANTS_NODES_CLAUSE_2 .format (
428- relationship_table = edge_model_table ,
429- pk_name = self .get_pk_name (),
413+ descendants_clauses_2 += (
414+ "\n "
415+ + DISALLOWED_DESCENDANTS_NODES_CLAUSE_2 .format (
416+ relationship_table = edge_model_table ,
417+ pk_name = self .get_pk_name (),
418+ )
430419 )
431420 query_parameters ["disallowed_downward_node_pks" ] = str (
432421 set (disallowed_nodes_queryset .values_list ("pk" , flat = True ))
@@ -437,13 +426,19 @@ def descendants_raw(self, max_depth=20, **kwargs):
437426
438427 # Nodes that MAY be included in the results
439428 if allowed_nodes_queryset is not None :
440- descendants_clauses_1 += "\n " + ALLOWED_DESCENDANTS_NODES_CLAUSE_1 .format (
441- relationship_table = edge_model_table ,
442- pk_name = self .get_pk_name (),
429+ descendants_clauses_1 += (
430+ "\n "
431+ + ALLOWED_DESCENDANTS_NODES_CLAUSE_1 .format (
432+ relationship_table = edge_model_table ,
433+ pk_name = self .get_pk_name (),
434+ )
443435 )
444- descendants_clauses_2 += "\n " + ALLOWED_DESCENDANTS_NODES_CLAUSE_2 .format (
445- relationship_table = edge_model_table ,
446- pk_name = self .get_pk_name (),
436+ descendants_clauses_2 += (
437+ "\n "
438+ + ALLOWED_DESCENDANTS_NODES_CLAUSE_2 .format (
439+ relationship_table = edge_model_table ,
440+ pk_name = self .get_pk_name (),
441+ )
447442 )
448443 query_parameters ["allowed_descendants_node_pks" ] = str (
449444 set (allowed_nodes_queryset .values_list ("pk" , flat = True ))
@@ -574,7 +569,7 @@ def path_raw(self, target_node, directional=True, max_depth=20, **kwargs):
574569 if fk_field_name is not None :
575570 downward_clauses += "\n " + PATH_LIMITING_FK_EDGES_CLAUSE .format (
576571 relationship_table = edge_model_table ,
577- pk_name = self .get_pk_name (),
572+ pk_name = self .get_pk_name (),
578573 fk_field_name = fk_field_name ,
579574 )
580575 query_parameters [
@@ -777,19 +772,25 @@ def descendants(self, node, **kwargs):
777772 """
778773 Returns a queryset of all edges descended from the given node
779774 """
780- return _filter_order (self .model .objects , "parent" , node .self_and_descendants (** kwargs ))
775+ return _filter_order (
776+ self .model .objects , "parent" , node .self_and_descendants (** kwargs )
777+ )
781778
782779 def ancestors (self , node , ** kwargs ):
783780 """
784781 Returns a queryset of all edges which are ancestors of the given node
785782 """
786- return _filter_order (self .model .objects , "child" , node .ancestors_and_self (** kwargs ))
783+ return _filter_order (
784+ self .model .objects , "child" , node .ancestors_and_self (** kwargs )
785+ )
787786
788787 def clan (self , node , ** kwargs ):
789788 """
790789 Returns a queryset of all edges for ancestors, self, and descendants
791790 """
792- return _filter_order (self .model .objects , ["parent" , "child" ], node .clan (** kwargs ))
791+ return _filter_order (
792+ self .model .objects , ["parent" , "child" ], node .clan (** kwargs )
793+ )
793794
794795 def path (self , start_node , end_node , ** kwargs ):
795796 """
@@ -826,7 +827,7 @@ def edge_factory(
826827 try :
827828 node_model_name = node_model .split ("." )[1 ]
828829 except IndexError :
829-
830+
830831 node_model_name = node_model
831832 else :
832833 node_model_name = node_model ._meta .model_name
0 commit comments