Coverage for src / lexigram / admin / relations / routes.py: 16%

50 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-13 22:14 +0800

1"""Route registration for relation managers.""" 

2 

3from __future__ import annotations 

4 

5from typing import TYPE_CHECKING, Any 

6 

7from starlette.responses import HTMLResponse 

8from starlette.routing import Route 

9 

10if TYPE_CHECKING: 

11 from starlette.requests import Request 

12 

13 from lexigram.admin.relations.manager_ext import RelationManager 

14 

15 

16def register_relation_routes( 

17 resource_name: str, 

18 manager_class: type[RelationManager], 

19) -> list[Route]: 

20 """Create Starlette Route objects for a relation manager.""" 

21 prefix = f"/{resource_name}" 

22 

23 async def _handle_list(request: Request) -> HTMLResponse: 

24 parent_id = request.path_params.get("parent_id", "") 

25 mgr = _create_manager(manager_class, parent_id) 

26 html = await mgr.render(request, resource_name) 

27 return HTMLResponse(html) 

28 

29 async def _handle_create_form(request: Request) -> HTMLResponse: 

30 parent_id = request.path_params.get("parent_id", "") 

31 mgr = _create_manager(manager_class, parent_id) 

32 form = mgr.create_form() 

33 return HTMLResponse(form or "<div>No create form available</div>") 

34 

35 async def _handle_create(request: Request) -> HTMLResponse: 

36 parent_id = request.path_params.get("parent_id", "") 

37 mgr = _create_manager(manager_class, parent_id) 

38 await mgr.get_query() 

39 html = await mgr.render(request, resource_name) 

40 return HTMLResponse(html) 

41 

42 async def _handle_edit_form(request: Request) -> HTMLResponse: 

43 parent_id = request.path_params.get("parent_id", "") 

44 record_id = request.path_params.get("record_id", "") 

45 mgr = _create_manager(manager_class, parent_id) 

46 record = await _get_record(mgr, record_id) 

47 form = mgr.edit_form(record) if record else None 

48 return HTMLResponse(form or f"<div>Edit form for {record_id}</div>") 

49 

50 async def _handle_update(request: Request) -> HTMLResponse: 

51 parent_id = request.path_params.get("parent_id", "") 

52 record_id = request.path_params.get("record_id", "") 

53 mgr = _create_manager(manager_class, parent_id) 

54 html = await mgr.render(request, resource_name) 

55 return HTMLResponse(html) 

56 

57 async def _handle_delete(request: Request) -> HTMLResponse: 

58 parent_id = request.path_params.get("parent_id", "") 

59 record_id = request.path_params.get("record_id", "") 

60 mgr = _create_manager(manager_class, parent_id) 

61 return HTMLResponse("") 

62 

63 return [ 

64 Route( 

65 path=f"{prefix}/{{parent_id}}/relations/{{rel_name}}", 

66 endpoint=_handle_list, 

67 methods=["GET"], 

68 ), 

69 Route( 

70 path=f"{prefix}/{{parent_id}}/relations/{{rel_name}}/new", 

71 endpoint=_handle_create_form, 

72 methods=["GET"], 

73 ), 

74 Route( 

75 path=f"{prefix}/{{parent_id}}/relations/{{rel_name}}", 

76 endpoint=_handle_create, 

77 methods=["POST"], 

78 ), 

79 Route( 

80 path=f"{prefix}/{{parent_id}}/relations/{{rel_name}}/{{record_id}}/edit", 

81 endpoint=_handle_edit_form, 

82 methods=["GET"], 

83 ), 

84 Route( 

85 path=f"{prefix}/{{parent_id}}/relations/{{rel_name}}/{{record_id}}", 

86 endpoint=_handle_update, 

87 methods=["PUT"], 

88 ), 

89 Route( 

90 path=f"{prefix}/{{parent_id}}/relations/{{rel_name}}/{{record_id}}", 

91 endpoint=_handle_delete, 

92 methods=["DELETE"], 

93 ), 

94 ] 

95 

96 

97def _create_manager( 

98 manager_class: type[RelationManager], parent_id: Any 

99) -> RelationManager: 

100 return manager_class(parent_id=parent_id) 

101 

102 

103async def _get_record(mgr: RelationManager, record_id: str) -> Any: 

104 items = await mgr.get_query() 

105 for item in items: 

106 if str(getattr(item, "id", "")) == record_id: 

107 return item 

108 return None 

109 

110 

111__all__ = [ 

112 "register_relation_routes", 

113]