Coverage for src/lexigram/admin/controllers/resource/detail.py: 96%

25 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-21 14:56 +0800

1"""Detail view for the resource controller.""" 

2 

3from __future__ import annotations 

4 

5from typing import TYPE_CHECKING 

6 

7from starlette.requests import Request 

8from starlette.responses import HTMLResponse, Response 

9 

10from lexigram.admin.controllers.resource.meta import T 

11from lexigram.admin.data.data_source import IDataSource as DataSourceProtocol 

12from lexigram.admin.state.context import AdminContext, AdminContextManager 

13from lexigram.ui import el, render_to_string 

14 

15if TYPE_CHECKING: 

16 from lexigram.admin.controllers.resource import ResourceController 

17 

18 

19 

20class ResourceDetailMixin: 

21 """Detail view and rendering.""" 

22 

23 async def detail(self: ResourceController, request: Request) -> Response: 

24 """View single resource.""" 

25 async with AdminContextManager(request) as ctx: 

26 item_id = request.path_params.get("id") 

27 

28 data_source = self.get_data_source() 

29 item = await data_source.find_one(item_id) 

30 

31 if item is None: 

32 from lexigram.admin.lib.template import render_error_page 

33 

34 html = render_error_page( 

35 status_code=404, 

36 title="Not Found", 

37 message=f"{self.meta.label} not found", 

38 ) 

39 return HTMLResponse(html, status_code=404) 

40 

41 if ctx.is_htmx: 

42 return HTMLResponse(self.render_detail_partial(ctx, item)) 

43 

44 return HTMLResponse(self.render_detail(ctx, item)) 

45 def render_detail(self: ResourceController, ctx: AdminContext, item: T) -> str: 

46 """Render full detail page. Override in subclass.""" 

47 return f""" 

48<!DOCTYPE html> 

49<html> 

50<head><title>{self.meta.label}</title></head> 

51<body> 

52 <h1>{self.meta.label}</h1> 

53 {self.render_detail_partial(ctx, item)} 

54</body> 

55</html> 

56""" 

57 

58 def render_detail_partial(self: ResourceController, ctx: AdminContext, item: T) -> str: 

59 """Render detail content. Override in subclass.""" 

60 return render_to_string(el("pre", str(item)))