Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1"""Schema.""" 

2# Pyramid 

3import colander 

4 

5# Deform 

6from deform.i18n import _ 

7 

8from . import widget 

9 

10 

11default_widget_makers = { 

12 colander.Mapping: widget.MappingWidget, 

13 colander.Sequence: widget.SequenceWidget, 

14 colander.String: widget.TextInputWidget, 

15 colander.Integer: widget.TextInputWidget, 

16 colander.Float: widget.TextInputWidget, 

17 colander.Decimal: widget.TextInputWidget, 

18 colander.Boolean: widget.CheckboxWidget, 

19 colander.Date: widget.DateInputWidget, 

20 colander.DateTime: widget.DateTimeInputWidget, 

21 colander.Tuple: widget.TextInputCSVWidget, 

22 colander.Time: widget.TimeInputWidget, 

23 colander.Money: widget.MoneyInputWidget, 

24 colander.Set: widget.CheckboxChoiceWidget, 

25} 

26 

27 

28@colander.deferred 

29def deferred_csrf_value(node, kw): 

30 return kw["request"].session.get_csrf_token() 

31 

32 

33class FileData(object): 

34 """ 

35 A type representing file data; used to shuttle data back and forth 

36 between an application and the 

37 :class:`deform.widget.FileUploadWidget` widget. 

38 

39 This type passes the value obtained during deserialization back to 

40 the caller unchanged (it will be an instance of 

41 ``deform.widget.filedict``, which is a plain dictionary subclass; 

42 it is only a dict subclass so ``isinstance`` may be used against 

43 it in highly generalized persistence circumstances to detect that 

44 it is file data). It serializes from a dictionary containing 

45 partial file data info into a dictionary containing full file data 

46 info, serializing the full file data (the widget receives the full 

47 file data). 

48 """ 

49 

50 # We cant use FileUploadWidget as the default_widget_maker for 

51 # this schema node because it requires a tmpstore argument, and 

52 # a tmpstore cannot be generally defaulted. 

53 

54 def serialize(self, node, value): 

55 """ 

56 Serialize a dictionary representing partial file information 

57 to a dictionary containing information expected by a file 

58 upload widget. 

59 

60 The file data dictionary passed as ``value`` to this 

61 ``serialize`` method *must* include: 

62 

63 filename 

64 Filename of this file (not a full filesystem path, just the 

65 filename itself). 

66 

67 uid 

68 Unique string id for this file. Needs to be unique enough to 

69 disambiguate it from other files that may use the same 

70 temporary storage mechanism before a successful validation, 

71 and must be adequate for the calling code to reidentify it 

72 after deserialization. 

73 

74 A fully populated dictionary *may* also include the following 

75 values: 

76 

77 fp 

78 File-like object representing this file's content or 

79 ``None``. ``None`` indicates this file has already been 

80 committed to permanent storage. When serializing a 

81 'committed' file, the ``fp`` value should ideally not be 

82 passed or it should be passed as ``None``; ``None`` as an 

83 ``fp`` value is a signifier to the file upload widget that 

84 the file data has already been committed. Using ``None`` 

85 as an ``fp`` value helps prevent unnecessary data copies 

86 to temporary storage when a form is rendered, however its 

87 use requires cooperation from the calling code; in 

88 particular, the calling code must be willing to translate 

89 a ``None`` ``fp`` value returned from a deserialization 

90 into the file data via the ``uid`` in the deserialization. 

91 

92 mimetype 

93 File content type (e.g. ``application/octet-stream``). 

94 

95 size 

96 File content length (integer). 

97 

98 preview_url 

99 URL which provides an image preview of this file's data. 

100 

101 If a ``size`` is not provided, the widget will have no access 

102 to size display data. If ``preview_url`` is not provided, the 

103 widget will not be able to show a file preview. If 

104 ``mimetype`` is not provided, the widget will not be able to 

105 display mimetype information. 

106 """ 

107 if value is colander.null: 

108 return colander.null 

109 

110 if not hasattr(value, "get"): 

111 mapping = {"value": repr(value)} 

112 raise colander.Invalid( 

113 node, _("${value} is not a dictionary", mapping=mapping) 

114 ) 

115 for n in ("filename", "uid"): 

116 if n not in value: 

117 mapping = {"value": repr(value), "key": n} 

118 raise colander.Invalid( 

119 node, _("${value} has no ${key} key", mapping=mapping) 

120 ) 

121 result = widget.filedict(value) 

122 # provide a value for these entries even if None 

123 result["mimetype"] = value.get("mimetype") 

124 result["size"] = value.get("size") 

125 result["fp"] = value.get("fp") 

126 result["preview_url"] = value.get("preview_url") 

127 return result 

128 

129 def deserialize(self, node, value): 

130 return value 

131 

132 def cstruct_children(self, node, cstruct): # pragma: no cover 

133 return [] 

134 

135 

136class CSRFSchema(colander.Schema): 

137 """ 

138 CSRF protected form schema. 

139 

140 Example: 

141 

142 .. code-block:: python 

143 

144 import colander 

145 from deform.schema import CSRFSchema 

146 

147 class MySchema(CSRFSchema): 

148 my_field = colander.SchemaNode(colander.String()) 

149 

150 And in your application code, *bind* the schema, passing the request as a 

151 keyword argument: 

152 

153 .. code-block:: python 

154 

155 def view(request): 

156 schema = MySchema().bind(request=request) 

157 

158 When using Pyramid 1.7+, the CSRF token is validated by CSRF view deriver. 

159 

160 More information 

161 

162 https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/sessions.html#checking-csrf-tokens-automatically # noqa: E501 

163 """ 

164 

165 csrf_token = colander.SchemaNode( 

166 colander.String(), 

167 widget=widget.HiddenWidget(), 

168 default=deferred_csrf_value, 

169 )