Coverage for gws-app/gws/plugin/model_field/text/__init__.py: 100%

33 statements  

« prev     ^ index     » next       coverage.py v7.17.0, created at 2026-10-23 20:06 +0200

1"""Text field. 

2 

3A scalar field for strings. Without a configured widget, the field uses an 

4``input`` widget. 

5 

6With ``textSearch``, the field takes part in keyword searches of database 

7models. The keyword is compared with the column value cast to a string: 

8 

9- ``exact``: the value equals the keyword, 

10- ``any``, ``begin``, ``end``: the keyword occurs anywhere, at the start or at 

11 the end of the value; ``%`` and ``_`` in the keyword are matched literally, 

12- ``like``: the keyword is used as an SQL ``LIKE`` pattern as is. 

13 

14The pattern match is case-insensitive (``ILIKE``) unless ``caseSensitive`` is set. 

15Keywords shorter than ``minLength`` are ignored. 

16 

17Example:: 

18 

19 fields+ { 

20 name "name" 

21 type "text" 

22 textSearch { type "begin" minLength 2 } 

23 } 

24""" 

25 

26from typing import Optional, cast 

27 

28import gws 

29import gws.base.database.model 

30import gws.base.database.util 

31import gws.base.model.scalar_field 

32import gws.lib.sa as sa 

33 

34 

35@gws.ext.config.modelField('text') 

36class Config(gws.base.model.scalar_field.Config): 

37 """Field for text values.""" 

38 

39 textSearch: Optional[gws.TextSearchOptions] 

40 """Keyword search options for the field.""" 

41 

42 

43@gws.ext.props.modelField('text') 

44class Props(gws.base.model.scalar_field.Props): 

45 pass 

46 

47 

48@gws.ext.object.modelField('text') 

49class Object(gws.base.model.scalar_field.Object): 

50 """Text field object.""" 

51 

52 attributeType = gws.AttributeType.str 

53 textSearch: Optional[gws.TextSearchOptions] 

54 """Keyword search options, or None if the field is not searchable.""" 

55 

56 def configure(self): 

57 self.textSearch = self.cfg('textSearch') 

58 if self.textSearch: 

59 self.supportsKeywordSearch = True 

60 

61 def configure_widget(self): 

62 if not super().configure_widget(): 

63 self.widget = self.root.create_shared(gws.ext.object.modelWidget, type='input') 

64 return True 

65 

66 ## 

67 

68 def before_select(self, mc): 

69 super().before_select(mc) 

70 

71 if not self.textSearch: 

72 return 

73 

74 model = cast(gws.base.database.model.Object, self.model) 

75 col = sa.cast(model.column(self.name), sa.String) 

76 

77 cond = gws.base.database.util.text_search_clause(col, mc.search.keyword, self.textSearch) 

78 if cond is not None: 

79 mc.dbSelect.keywordWhere.append(cond)