|
@@ -1,190 +1,493 @@
|
1
|
1
|
#-*- coding: utf-8 -*-
|
2
|
2
|
|
3
|
|
-from Lodel.utils.mlstring import MlString
|
4
|
|
-import datetime
|
5
|
3
|
from django.db import models
|
|
4
|
+import re
|
|
5
|
+import datetime
|
|
6
|
+import json
|
|
7
|
+import importlib
|
|
8
|
+import copy
|
|
9
|
+import EditorialModel
|
|
10
|
+from Lodel.utils.mlstring import MlString
|
6
|
11
|
|
7
|
12
|
|
8
|
|
-##
|
|
13
|
+## @brief Characterise fields for LeObject and EmComponent
|
|
14
|
+# This class handles values rules for LeObject and EmComponents.
|
9
|
15
|
#
|
10
|
|
-# returns an instance of the corresponding EmFieldType class for a given name
|
|
16
|
+# It allows to EmFieldValue classes family to have rules to cast, validate and save values.
|
11
|
17
|
#
|
12
|
|
-# @param name str: name of the field type
|
13
|
|
-# @param kwargs dict: options of the field type
|
14
|
|
-# @return EmFieldType
|
15
|
|
-def get_field_type(name):
|
16
|
|
- class_name = 'EmField_'+name
|
17
|
|
- constructor = globals()[class_name]
|
18
|
|
- instance = constructor()
|
19
|
|
- return instance
|
20
|
|
-
|
21
|
|
-
|
22
|
|
-##
|
|
18
|
+# There is exposed methods that allows LeObject and EmType to run a save sequence. This methods are :
|
|
19
|
+# - EmFieldType.to_value() That cast a value to an EmFieldType internal storage
|
|
20
|
+# - EmFieldType.is_valid() That indicates wether or not a value is valid
|
|
21
|
+# - EmFieldType.pre_save() That returns weighted SQL request that must be run before any value save @ref EditorialModel::types::EmType.save_values()
|
|
22
|
+# - EmFieldType.to_sql() That returns a value that can be inserted in database.
|
|
23
|
+# - EmFieldType.post_save() That returns weighted SQL request that must be run after any value save @ref EditorialModel::types::EmType.save_values()
|
23
|
24
|
#
|
24
|
|
-# Generic Field type
|
25
|
|
-class EmFieldType():
|
26
|
|
-
|
|
25
|
+class EmFieldType(object):
|
|
26
|
+
|
|
27
|
+ ## Stores options and default value for EmFieldType
|
|
28
|
+ # options list :
|
|
29
|
+ # - type (str|None) : if None will make an 'abstract' fieldtype (with no value assignement possible)
|
|
30
|
+ # - nullable (bool) : tell whether or not a fieldType accept NULL value
|
|
31
|
+ # - default (mixed) : The default value for a FieldType
|
|
32
|
+ # - primarykey (bool) : If true the fieldType represent a PK
|
|
33
|
+ # - autoincrement (bool) : If true the fieldType will be autoincremented
|
|
34
|
+ # - index (bool) : If true the columns will be indexed in Db
|
|
35
|
+ # - name (str) : FieldType name
|
|
36
|
+ # - doc (str) : FieldType documentation
|
|
37
|
+ # - onupdate (callable) : A callback to call on_update
|
|
38
|
+ # - valueobject (EmFieldValue or childs) : An object that represent values for this fieldType
|
|
39
|
+ # - type_* (mixed) : Use to construct an options dictinnary for a type (exemple : type_length => nnewColumn(lenght= [type_lenght VALUE] )) @ref EmFieldSQLType
|
|
40
|
+ # - validators (list) : List of validator functions to use
|
|
41
|
+ _opt = {
|
|
42
|
+ 'name': None,
|
|
43
|
+ 'type': None,
|
|
44
|
+ 'nullable': True,
|
|
45
|
+ 'default': None,
|
|
46
|
+ 'primarykey': False,
|
|
47
|
+ 'autoincrement': False,
|
|
48
|
+ 'uniq': False,
|
|
49
|
+ 'index': False,
|
|
50
|
+ 'doc': None,
|
|
51
|
+ 'onupdate': None,
|
|
52
|
+ 'valueobject': None,
|
|
53
|
+ 'validators': None
|
|
54
|
+ }
|
|
55
|
+
|
|
56
|
+ ## Instanciate an EmFieldType
|
|
57
|
+ # For arguments see @ref EmFieldType::_opt
|
|
58
|
+ # @see EmFieldType::_opt
|
27
|
59
|
def __init__(self, **kwargs):
|
28
|
|
- self.name = kwargs['name'] #TODO gérer le cas où le name n'est pas passé
|
29
|
|
- self.value = None
|
30
|
|
- self.options = kwargs
|
31
|
|
-
|
32
|
|
- def from_python(self, value):
|
33
|
|
- self.value = value
|
34
|
|
-
|
35
|
|
-
|
36
|
|
-##
|
37
|
|
-#
|
38
|
|
-# Integer field type
|
39
|
|
-class EmField_integer(EmFieldType):
|
40
|
|
-
|
41
|
|
- def __init__(self, **kwargs):
|
42
|
|
- super(EmField_integer, self).__init__(**kwargs)
|
43
|
|
-
|
44
|
|
- def to_django(self):
|
45
|
|
- return models.IntegerField(**self.options)
|
46
|
|
-
|
47
|
|
-
|
48
|
|
-##
|
49
|
|
-#
|
50
|
|
-# Boolean field type
|
51
|
|
-class EmField_boolean(EmFieldType):
|
52
|
|
-
|
53
|
|
- def __init__(self):
|
54
|
|
- super(EmField_boolean, self).__init__(**kwargs)
|
55
|
|
-
|
56
|
|
- def to_django(self):
|
57
|
|
- if 'nullable' in self.options and self.options['nullable'] == 'true':
|
58
|
|
- return models.NullBooleanField(**self.options)
|
|
60
|
+ self.__init(kwargs)
|
|
61
|
+ self.type_options = dict()
|
|
62
|
+
|
|
63
|
+ # stores all col_* arguments into the self.type_options dictionary
|
|
64
|
+ args = kwargs.copy()
|
|
65
|
+ for optname in args:
|
|
66
|
+ type_opt = re.sub(r'^type_', '', optname)
|
|
67
|
+ if type_opt != optname:
|
|
68
|
+ self.type_options[type_opt] = args[optname]
|
|
69
|
+ del kwargs[optname]
|
|
70
|
+
|
|
71
|
+ # checks if the other arguments are valid
|
|
72
|
+ if len(set(kwargs.keys()) - set(self.__class__._opt.keys())) > 0:
|
|
73
|
+ badargs = ""
|
|
74
|
+ for bad in set(kwargs.keys()) - set(self.__class__._opt.keys()):
|
|
75
|
+ badargs += " " + bad
|
|
76
|
+ raise TypeError("Unexpected arguments : %s" % badargs)
|
|
77
|
+
|
|
78
|
+ # stores other arguments as instance attribute
|
|
79
|
+ for opt_name in self.__class__._opt:
|
|
80
|
+ setattr(self, opt_name, (kwargs[opt_name] if opt_name in kwargs else self.__class__._opt[opt_name]))
|
|
81
|
+
|
|
82
|
+ # checks type's options valididty
|
|
83
|
+ if self.type != None:
|
|
84
|
+ try:
|
|
85
|
+ EmFieldSQLType.sqlType(self.type, **self.type_options)
|
|
86
|
+ except TypeError as e:
|
|
87
|
+ raise e
|
|
88
|
+
|
|
89
|
+ # Default value for name
|
|
90
|
+ if self.name == None:
|
|
91
|
+ if self.__class__ == EmFieldType:
|
|
92
|
+ self.name = 'generic'
|
|
93
|
+ else:
|
|
94
|
+ self.name = self.__class__.__name__
|
|
95
|
+
|
|
96
|
+ # Default value for doc
|
|
97
|
+ if self.doc == None:
|
|
98
|
+ if self.__class__ == EmFieldType:
|
|
99
|
+ self.doc = 'Abstract generic EmFieldType'
|
|
100
|
+ else:
|
|
101
|
+ self.doc = self.__class__.__name__
|
|
102
|
+
|
|
103
|
+ ## MUST be called first in each constructor
|
|
104
|
+ # @todo this solution is not good (look at the __init__ for EmFieldType childs)
|
|
105
|
+ def __init(self, kwargs):
|
|
106
|
+ try:
|
|
107
|
+ self.args_copy
|
|
108
|
+ except AttributeError:
|
|
109
|
+ self.args_copy = kwargs.copy()
|
|
110
|
+
|
|
111
|
+ @property
|
|
112
|
+ ## A predicate that indicates whether or not an EmFieldType is "abstract"
|
|
113
|
+ def is_abstract(self):
|
|
114
|
+ return (self.type == None)
|
|
115
|
+
|
|
116
|
+ ## Returns a copy of the current EmFieldType
|
|
117
|
+ def copy(self):
|
|
118
|
+ args = self.args_copy.copy()
|
|
119
|
+ return self.__class__(**args)
|
|
120
|
+
|
|
121
|
+ def dump_opt(self):
|
|
122
|
+ return json.dumps(self.args_copy)
|
|
123
|
+
|
|
124
|
+ @staticmethod
|
|
125
|
+ ## Return an instance from a classname and options from dump_opt
|
|
126
|
+ # @param classname str: The EmFieldType class name
|
|
127
|
+ # @param json_opt str: getted from dump_opt
|
|
128
|
+ def restore(colname, classname, json_opt):
|
|
129
|
+ field_type_class = getattr(EditorialModel.fieldtypes, classname)
|
|
130
|
+ init_opt = json.loads(json_opt)
|
|
131
|
+ init_opt['name'] = colname
|
|
132
|
+ return field_type_class(**init_opt)
|
|
133
|
+
|
|
134
|
+ ## Return a value object 'driven' by this EmFieldType
|
|
135
|
+ # @param name str: The column name associated with the value
|
|
136
|
+ # @param *init_val mixed: If given this will be the initialisation value
|
|
137
|
+ # @return a EmFieldValue instance
|
|
138
|
+ # @todo better default value (and bad values) handling
|
|
139
|
+ def valueObject(self, name, *init_val):
|
|
140
|
+ if self.valueObject == None:
|
|
141
|
+ return EmFieldValue(name, self, *init_val)
|
|
142
|
+ return self.valueObject(name, self, *init_val)
|
|
143
|
+
|
|
144
|
+ ## Cast to the correct value
|
|
145
|
+ # @param v mixed : the value to cast
|
|
146
|
+ # @return A gently casted value
|
|
147
|
+ # @throw ValueError if v is innapropriate
|
|
148
|
+ # @throw NotImplementedError if self is an abstract EmFieldType
|
|
149
|
+ def to_value(self, v):
|
|
150
|
+ if self.type == None:
|
|
151
|
+ raise NotImplemented("This EmFieldType is abstract")
|
|
152
|
+ if v == None and not self.nullable:
|
|
153
|
+ raise TypeError("Field not nullable")
|
|
154
|
+ return v
|
|
155
|
+
|
|
156
|
+ ## to_value alias
|
|
157
|
+ # @param value mixed : the value to cast
|
|
158
|
+ # @return A casted value
|
|
159
|
+ def from_string(self, value):
|
|
160
|
+ return self.to_value(value)
|
|
161
|
+
|
|
162
|
+ ## Returns a gently sql forged value
|
|
163
|
+ # @return A sql forged value
|
|
164
|
+ # @warning It assumes that the value is correct and comes from an EmFieldValue object
|
|
165
|
+ def to_sql(self, value):
|
|
166
|
+ if self.is_abstract:
|
|
167
|
+ raise NotImplementedError("This EmFieldType is abstract")
|
|
168
|
+ return True
|
|
169
|
+
|
|
170
|
+ ## Returns whether or not a value is valid for this EmFieldType
|
|
171
|
+ # @note This function always returns True and is here for being overloaded by child objects
|
|
172
|
+ # @return A boolean, True if valid else False
|
|
173
|
+ def is_valid(self, value):
|
|
174
|
+ if self.is_abstract:
|
|
175
|
+ raise NotImplementedError("This EmFieldType is abstract")
|
|
176
|
+ return True
|
|
177
|
+
|
|
178
|
+ ## Pre-save actions
|
|
179
|
+ def pre_save(self):
|
|
180
|
+ if self.is_abstract:
|
|
181
|
+ raise NotImplementedError("This EmFieldType is abstract")
|
|
182
|
+ return []
|
|
183
|
+
|
|
184
|
+ ## Post-save actions
|
|
185
|
+ def post_save(self):
|
|
186
|
+ if self.is_abstract:
|
|
187
|
+ raise NotImplementedError("This EmFieldType is abstract")
|
|
188
|
+ return []
|
|
189
|
+
|
|
190
|
+ @classmethod
|
|
191
|
+ ## Function designed to be called by child class to enforce a type
|
|
192
|
+ # @param args dict: The kwargs argument of __init__
|
|
193
|
+ # @param typename str: The typename to enforce
|
|
194
|
+ # @return The new kwargs to be used
|
|
195
|
+ # @throw TypeError if type is present is args
|
|
196
|
+ def _setType(cl, args, typename):
|
|
197
|
+ return cl._argEnforce(args, 'type', typename, True)
|
|
198
|
+
|
|
199
|
+ @classmethod
|
|
200
|
+ ## Function designed to be called by child's constructo to enforce an argument
|
|
201
|
+ # @param args dict: The constructor's kwargs
|
|
202
|
+ # @param argname str: The name of the argument to enforce
|
|
203
|
+ # @param argval mixed: The value we want to enforce
|
|
204
|
+ # @param Return a new kwargs
|
|
205
|
+ # @throw TypeError if type is present is args and exception argument is True
|
|
206
|
+ def _argEnforce(cl, args, argname, argval, exception=True):
|
|
207
|
+ if exception and argname in args:
|
|
208
|
+ raise TypeError("Invalid argument '"+argname+"' for "+cl.__class__.__name__+" __init__")
|
|
209
|
+ args[argname] = argval
|
|
210
|
+ return args
|
|
211
|
+
|
|
212
|
+ @classmethod
|
|
213
|
+ ## Function designed to be called by child's constructor to set a default value
|
|
214
|
+ # @param args dict: The constructor's kwargs
|
|
215
|
+ # @param argname str: The name of the argument with default value
|
|
216
|
+ # @param argval mixed : The default value
|
|
217
|
+ # @return a new kwargs dict
|
|
218
|
+ def _argDefault(cl, args, argname, argval):
|
|
219
|
+ if argname not in args:
|
|
220
|
+ args[argname] = argval
|
|
221
|
+ return args
|
|
222
|
+
|
|
223
|
+class EmFieldValue(object):
|
|
224
|
+
|
|
225
|
+ ## Instanciates a EmFieldValue
|
|
226
|
+ # @param name str : The column name associated with this value
|
|
227
|
+ # @param fieldtype EmFieldType: The EmFieldType defining the value
|
|
228
|
+ # @param *value *list: This argument allow to pass a value to set (even None) and to detect if no value given to set to EmFieldType's default value
|
|
229
|
+ # @throw TypeError if more than 2 arguments given
|
|
230
|
+ # @throw TypeError if fieldtype is not an EmFieldType
|
|
231
|
+ # @throw TypeError if fieldtype is an abstract EmFieldType
|
|
232
|
+ def __init__(self, name, fieldtype, *value):
|
|
233
|
+ if not isinstance(fieldtype, EmFieldType):
|
|
234
|
+ raise TypeError("Expected <class EmFieldType> for 'fieldtype' argument, but got : %s instead" % str(type(fieldtype)))
|
|
235
|
+ if fieldtype.is_abstract:
|
|
236
|
+ raise TypeError("The given fieldtype in argument is abstract.")
|
|
237
|
+
|
|
238
|
+ # This copy ensures that the fieldtype will not change during the value lifecycle
|
|
239
|
+ super(EmFieldValue, self).__setattr__('fieldtype', fieldtype.copy())
|
|
240
|
+
|
|
241
|
+ if len(value) > 1:
|
|
242
|
+ raise TypeError("Accept only 2 positionnal parameters. %s given." % str(len(value)+1))
|
|
243
|
+ elif len(value) == 1:
|
|
244
|
+ self.value = value[0]
|
59
|
245
|
else:
|
60
|
|
- return models.BooleanField(**self.options)
|
61
|
|
-
|
62
|
|
-##
|
63
|
|
-#
|
64
|
|
-# Varchar field type
|
65
|
|
-class EmField_char(EmFieldType):
|
|
246
|
+ self.value = fieldtype.default
|
|
247
|
+
|
|
248
|
+ # Use this to set value in the constructor
|
|
249
|
+ setv = super(EmFieldValue, self).__setattr__
|
|
250
|
+ # This copy makes column attributes accessible easily
|
|
251
|
+ for attrname in self.fieldtype.__dict__:
|
|
252
|
+ setv(attrname, getattr(self.fieldtype, attrname))
|
|
253
|
+
|
|
254
|
+ # Assign some EmFieldType methods to the value
|
|
255
|
+ setv('from_python', self.fieldtype.to_value)
|
|
256
|
+ setv('from_string', self.fieldtype.to_value)
|
|
257
|
+ #setv('sqlCol', self.fieldtype.sqlCol)
|
|
258
|
+
|
|
259
|
+ ## The only writable attribute of EmFieldValue is the value
|
|
260
|
+ # @param name str: Have to be value
|
|
261
|
+ # @param value mixed: The value to set
|
|
262
|
+ # @throw AtrributeError if another attribute than value is to be set
|
|
263
|
+ # @throw ValueError if self.to_value raises it
|
|
264
|
+ # @see EmFieldType::to_value()
|
|
265
|
+ def __setattr__(self, name, value):
|
|
266
|
+ if name != "value":
|
|
267
|
+ raise AttributeError("EmFieldValue has only the value property settable")
|
|
268
|
+ super(EmFieldValue,self).__setattr__('value', self.fieldtype.to_value(value))
|
|
269
|
+
|
|
270
|
+ ##
|
|
271
|
+ # @warning When getting the fieldtype you actually get a copy of it to prevent any modifications !
|
|
272
|
+ def __getattr__(self, name):
|
|
273
|
+ if name == 'fieldtype':
|
|
274
|
+ return self.fieldtype.copy()
|
|
275
|
+ return super(EmFieldValue, self).__getattribute__(name)
|
|
276
|
+
|
|
277
|
+ ## @brief Return a valid SQL value
|
|
278
|
+ #
|
|
279
|
+ # Can be used to convert any value (giving one positionnal argument) or to return the current value
|
|
280
|
+ # @param *value list: If a positionnal argument is given return it and not the instance value
|
|
281
|
+ # @return A value suitable for sql
|
|
282
|
+ def to_sql(self, *value):
|
|
283
|
+ if len(value) > 1:
|
|
284
|
+ raise TypeError("Excepted 0 or 1 positional argument but got "+str(len(value)))
|
|
285
|
+ elif len(value) == 1:
|
|
286
|
+ return self.fieldtype.to_sql(value[0])
|
|
287
|
+ return self.fieldtype.to_sql(self.value)
|
|
288
|
+
|
|
289
|
+class EmFieldSQLType(object):
|
|
290
|
+ _integer = {'sql': models.IntegerField}
|
|
291
|
+ _bigint = {'sql': models.BigIntegerField}
|
|
292
|
+ _smallint = {'sql': models.SmallIntegerField}
|
|
293
|
+ _boolean = {'sql': models.BooleanField}
|
|
294
|
+ _nullableboolean = {'sql': models.NullBooleanField}
|
|
295
|
+ _float = {'sql': models.FloatField}
|
|
296
|
+ _varchar = {'sql': models.CharField}
|
|
297
|
+ _text = {'sql': models.TextField}
|
|
298
|
+ _time = {'sql': models.TimeField}
|
|
299
|
+ _date = {'sql': models.DateField}
|
|
300
|
+ _datetime = {'sql': models.DateTimeField}
|
|
301
|
+
|
|
302
|
+ _names = {
|
|
303
|
+ 'int': _integer,
|
|
304
|
+ 'integer': _integer,
|
|
305
|
+ 'bigint': _bigint,
|
|
306
|
+ 'smallint': _smallint,
|
|
307
|
+ 'boolean': _boolean,
|
|
308
|
+ 'bool': _boolean,
|
|
309
|
+ 'float': _float,
|
|
310
|
+ 'char': _varchar,
|
|
311
|
+ 'varchar': _varchar,
|
|
312
|
+ 'text': _text,
|
|
313
|
+ 'time': _time,
|
|
314
|
+ 'date': _date,
|
|
315
|
+ 'datetime': _datetime,
|
|
316
|
+ }
|
|
317
|
+
|
|
318
|
+ @classmethod
|
|
319
|
+ def sqlType(cls, name, **kwargs):
|
|
320
|
+ if not isinstance(name, str):
|
|
321
|
+ raise TypeError("Expect <class str>, <class int>|None but got : %s %s" % (str(type(name)), str(type(size))))
|
|
322
|
+ name = name.lower()
|
|
323
|
+ if name not in cls._names:
|
|
324
|
+ raise ValueError("Unknown type '%s'" % name)
|
|
325
|
+
|
|
326
|
+ if name in ['boolean','bool'] and kwargs['nullable'] in [1,'true']:
|
|
327
|
+ sqlclass = _nullableboolean
|
|
328
|
+ else:
|
|
329
|
+ sqlclass = cls._names[name]
|
66
|
330
|
|
67
|
|
- def __init__(self, **kwargs):
|
68
|
|
- super(EmField_char, self).__init__(**kwargs)
|
|
331
|
+ if len(kwargs) == 0:
|
|
332
|
+ return sqlclass['sql']
|
69
|
333
|
|
70
|
|
- def to_django(self):
|
71
|
|
- return models.CharField(**self.options)
|
|
334
|
+ return sqlclass['sql'](**kwargs)
|
72
|
335
|
|
73
|
336
|
|
74
|
|
-##
|
75
|
|
-#
|
76
|
|
-# Date field type
|
77
|
|
-class EmField_date(EmFieldType):
|
|
337
|
+## @brief Represents values with common arithmetic operations
|
|
338
|
+class EmFieldValue_int(EmFieldValue):
|
|
339
|
+ def __int__(self):
|
|
340
|
+ return self.value
|
78
|
341
|
|
79
|
|
- def __init__(self, **kwargs):
|
80
|
|
- super(EmField_date, self).__init__(**kwargs)
|
|
342
|
+ def __add__(self, other):
|
|
343
|
+ return self.value + other
|
81
|
344
|
|
82
|
|
- def to_django(self):
|
83
|
|
- return models.DateField(**self.options)
|
|
345
|
+ def __sub__(self, other):
|
|
346
|
+ return self.value - other
|
84
|
347
|
|
|
348
|
+ def __mul__(self, other):
|
|
349
|
+ return self.value * other
|
85
|
350
|
|
86
|
|
-##
|
87
|
|
-#
|
88
|
|
-# Text field type
|
89
|
|
-class EmField_text(EmFieldType):
|
90
|
|
- def __init__(self, **kwargs):
|
91
|
|
- super(EmField_text, self).__init__(**kwargs)
|
|
351
|
+ def __div__(self, other):
|
|
352
|
+ return self.value / other
|
92
|
353
|
|
93
|
|
- def to_django(self):
|
94
|
|
- return models.TextField(**self.options)
|
|
354
|
+ def __mod__(self, other):
|
|
355
|
+ return self.value % other
|
95
|
356
|
|
|
357
|
+ def __iadd__(self, other):
|
|
358
|
+ self.value = int(self.value + other)
|
|
359
|
+ return self
|
96
|
360
|
|
97
|
|
-##
|
98
|
|
-#
|
99
|
|
-# Image field type
|
100
|
|
-class EmField_image(EmFieldType):
|
|
361
|
+ def __isub__(self, other):
|
|
362
|
+ self.value = int(self.value - other)
|
|
363
|
+ return self
|
101
|
364
|
|
102
|
|
- def __init__(self, **kwargs):
|
103
|
|
- super(EmField_image, self).__init__(**kwargs)
|
|
365
|
+ def __imul__(self, other):
|
|
366
|
+ self.value = int(self.value * other)
|
|
367
|
+ return self
|
104
|
368
|
|
105
|
|
- def to_django(self):
|
106
|
|
- return models.ImageField(**self.options)
|
|
369
|
+ def __idiv__(self, other):
|
|
370
|
+ self.value = int(self.value / other)
|
|
371
|
+ return self
|
107
|
372
|
|
108
|
373
|
|
109
|
|
-##
|
110
|
|
-#
|
111
|
|
-# File field type
|
112
|
|
-class EmField_file(EmFieldType):
|
|
374
|
+## @brief Handles integer fields
|
|
375
|
+# @note Enforcing type to be int
|
|
376
|
+# @note Default name is 'integer' and default 'valueobject' is EmFieldValue_int
|
|
377
|
+class EmField_integer(EmFieldType):
|
113
|
378
|
|
114
|
379
|
def __init__(self, **kwargs):
|
115
|
|
- super(EmField_file, self).__init__(**kwargs)
|
|
380
|
+ self._init(kwargs)
|
|
381
|
+ # Default name
|
|
382
|
+ kwargs = self.__class__._argDefault(kwargs, 'name', 'integer')
|
|
383
|
+ # Default value object
|
|
384
|
+ kwargs = self.__class__._argDefault(kwargs, 'valueobject', EmFieldValue_int)
|
|
385
|
+ # Type enforcing
|
|
386
|
+ kwargs = self.__class__._setType(kwargs, 'int')
|
|
387
|
+ super(EmField_integer, self).__init__(**kwargs)
|
116
|
388
|
|
117
|
|
- def to_django(self):
|
118
|
|
- return models.FileField(**self.options)
|
|
389
|
+ ##
|
|
390
|
+ # @todo catch cast error ?
|
|
391
|
+ def to_sql(self, value):
|
|
392
|
+ return value
|
119
|
393
|
|
|
394
|
+ def to_value(self, value):
|
|
395
|
+ if value == None:
|
|
396
|
+ return super(EmField_integer, self).to_value(value)
|
|
397
|
+ return int(value)
|
120
|
398
|
|
121
|
|
-##
|
122
|
|
-#
|
123
|
|
-# URL field type
|
124
|
|
-class EmField_url(EmFieldType):
|
125
|
399
|
|
|
400
|
+## @brief Handles boolean fields
|
|
401
|
+# @note Enforce type to be 'boolean'
|
|
402
|
+# @note Default name is 'boolean'
|
|
403
|
+class EmField_boolean(EmFieldType):
|
126
|
404
|
def __init__(self, **kwargs):
|
127
|
|
- super(EmField_url, self).__init__(**kwargs)
|
|
405
|
+ self._init(kwargs)
|
|
406
|
+ #Default name
|
|
407
|
+ kwargs = self.__class__._argDefault(kwargs, 'name', 'boolean')
|
|
408
|
+ #Type enforcing
|
|
409
|
+ kwargs = self.__class__._setType(kwargs, 'boolean')
|
|
410
|
+ super(EmField_boolean, self).__init__(**kwargs)
|
|
411
|
+ pass
|
128
|
412
|
|
129
|
|
- def to_django(self):
|
130
|
|
- return models.URLField(**self.options)
|
|
413
|
+ def to_sql(self, value):
|
|
414
|
+ return 1 if super(EmField_boolean, self).to_sql(value) else 0
|
131
|
415
|
|
|
416
|
+ def to_value(self, value):
|
|
417
|
+ if value == None:
|
|
418
|
+ return super(EmField_boolean, self).to_value(value)
|
|
419
|
+ self.value = bool(value)
|
|
420
|
+ return self.value
|
132
|
421
|
|
133
|
|
-##
|
134
|
|
-#
|
135
|
|
-# Email field type
|
136
|
|
-class EmField_email(EmFieldType):
|
137
|
422
|
|
|
423
|
+## @brief Handles string fields
|
|
424
|
+# @note Enforce type to be (varchar)
|
|
425
|
+# @note Default 'name' is 'char'
|
|
426
|
+# @note Default 'type_length' is 76
|
|
427
|
+class EmField_char(EmFieldType):
|
|
428
|
+ default_length = 76
|
138
|
429
|
def __init__(self, **kwargs):
|
139
|
|
- super(EmField_email, self).__init__(**kwargs)
|
140
|
|
-
|
141
|
|
- def to_django(self):
|
142
|
|
- return models.EmailField(**self.options)
|
|
430
|
+ self._init(kwargs)
|
|
431
|
+ kwargs = self.__class__._argDefault(kwargs, 'type_length', self.__class__.default_length)
|
|
432
|
+ kwargs = self.__class__._argDefault(kwargs, 'name', 'char')
|
|
433
|
+ #Type enforcing
|
|
434
|
+ kwargs = self.__class__._setType(kwargs, 'varchar')
|
|
435
|
+ super(EmField_char, self).__init__(**kwargs)
|
|
436
|
+ def to_sql(self, value):
|
|
437
|
+ return str(value)
|
143
|
438
|
|
144
|
439
|
|
145
|
|
-##
|
146
|
|
-#
|
147
|
|
-# Datetime field type
|
148
|
|
-class EmField_datetime(EmFieldType):
|
149
|
|
-
|
|
440
|
+## @brief Handles date fields
|
|
441
|
+# @note Enforce type to be 'datetime'
|
|
442
|
+# @todo rename to EmField_datetime
|
|
443
|
+# @todo timezones support
|
|
444
|
+class EmField_date(EmFieldType):
|
150
|
445
|
def __init__(self, **kwargs):
|
151
|
|
- super(EmField_datetime, self).__init__(**kwargs)
|
152
|
|
-
|
153
|
|
- def to_django(self):
|
154
|
|
- return models.DateTimeField(**self.options)
|
155
|
|
-
|
|
446
|
+ self._init(kwargs)
|
|
447
|
+ kwargs = self.__class__._argDefault(kwargs, 'name', 'date')
|
|
448
|
+ #Type enforcing
|
|
449
|
+ kwargs = self.__class__._setType(kwargs, 'datetime')
|
|
450
|
+ super(EmField_date, self).__init__(**kwargs)
|
156
|
451
|
|
157
|
|
-##
|
158
|
|
-#
|
159
|
|
-# Time field type
|
160
|
|
-class EmField_time(EmFieldType):
|
|
452
|
+ def to_sql(self, value):
|
|
453
|
+ return value #thanks to sqlalchemy
|
161
|
454
|
|
162
|
|
- def __init__(self, **kwargs):
|
163
|
|
- super(EmField_datetime, self).__init__(**kwargs)
|
|
455
|
+ def to_value(self, value):
|
|
456
|
+ if value == None:
|
|
457
|
+ return super(EmField_date, self).to_value(value)
|
|
458
|
+ if isinstance(value, int):
|
|
459
|
+ #assume its a timestamp
|
|
460
|
+ return datetime.fromtimestamp(value)
|
|
461
|
+ if isinstance(value, datetime.datetime):
|
|
462
|
+ return value
|
164
|
463
|
|
165
|
|
- def to_django(self):
|
166
|
|
- return models.TimeField(**self.options)
|
167
|
464
|
|
168
|
|
-
|
169
|
|
-##
|
170
|
|
-#
|
171
|
|
-# mlstring field type
|
|
465
|
+## @brief Handles strings with translations
|
172
|
466
|
class EmField_mlstring(EmField_char):
|
173
|
467
|
|
174
|
468
|
def __init__(self, **kwargs):
|
|
469
|
+ self._init(kwargs)
|
|
470
|
+ kwargs = self.__class__._argDefault(kwargs, 'name', 'mlstr')
|
175
|
471
|
super(EmField_mlstring, self).__init__(**kwargs)
|
176
|
472
|
|
177
|
|
- def to_django(self):
|
178
|
|
- return models.CharField(**self.options)
|
|
473
|
+ def to_sql(self, value):
|
|
474
|
+ return value.__str__()
|
179
|
475
|
|
|
476
|
+ def to_value(self, value):
|
|
477
|
+ if value == None:
|
|
478
|
+ return super(EmField_mlstring, self).to_value(value)
|
|
479
|
+ if isinstance(value, str):
|
|
480
|
+ return MlString.load(value)
|
|
481
|
+ elif isinstance(value, MlString):
|
|
482
|
+ return value
|
|
483
|
+ raise TypeError("<class str> or <class MlString> excepted. But got "+str(type(value)))
|
180
|
484
|
|
181
|
|
-##
|
182
|
|
-#
|
183
|
|
-# Icon field type
|
184
|
|
-class EmField_icon(EmField_char):
|
185
|
485
|
|
|
486
|
+## @brief Handles lodel uid fields
|
|
487
|
+class EmField_uid(EmField_integer):
|
186
|
488
|
def __init__(self, **kwargs):
|
187
|
|
- super(EmField_icon, self).__init__(**kwargs)
|
|
489
|
+ self._init(kwargs)
|
|
490
|
+ kwargs = self.__class__._argEnforce(kwargs, 'primarykey', True)
|
|
491
|
+ super(EmField_uid, self).__init__(**kwargs)
|
|
492
|
+ pass
|
188
|
493
|
|
189
|
|
- def to_django(self):
|
190
|
|
- return models.CharField(**self.options)
|