Browse Source

New version of fieldtypes class hierarchy + partial migrationhandler adaptation

Yann Weber 8 years ago
parent
commit
bbf33373d0

+ 80
- 0
DataSource/MySQL/fieldtypes.py View File

@@ -0,0 +1,80 @@
1
+#-*- coding: utf-8 -*-
2
+
3
+## @package DataSource.MySQL.fieldtypes 
4
+# 
5
+# Defines usefull function to handle fieldtype in MySQL datasource
6
+
7
+import EditorialModel
8
+from EditorialModel import fieldtypes as ed_fieldtypes
9
+import EditorialModel.fieldtypes.generic
10
+from EditorialModel.fieldtypes.generic import SingleValueFieldType, MultiValueFieldType, ReferenceFieldType
11
+import EditorialModel.fieldtypes.integer
12
+import EditorialModel.fieldtypes.char
13
+import EditorialModel.fieldtypes.bool
14
+import EditorialModel.fieldtypes.text
15
+import EditorialModel.fieldtypes.rel2type
16
+
17
+## @brief Returns column specs from fieldtype
18
+# @param emfieldtype EmFieldType : An EmFieldType insance
19
+# @todo escape default value
20
+def singlevaluefieldtype_db_init_specs(emfieldtype):
21
+    colspec = ''
22
+    if not emfieldtype.nullable:
23
+        colspec = 'NOT NULL'
24
+    if hasattr(emfieldtype, 'default'):
25
+        colspec += ' DEFAULT '
26
+        if emfieldtype.default is None:
27
+            colspec += 'NULL '
28
+        else:
29
+            colspec += emfieldtype.default  # ESCAPE VALUE HERE !!!!
30
+
31
+    if emfieldtype.name == 'pk':
32
+        colspec += ' AUTO_INCREMENT'
33
+
34
+    return colspec
35
+
36
+## @brief Given a fieldtype return instructions to be executed by the migration handler
37
+#
38
+# The returned value in a tuple of len = 3
39
+#
40
+# The first items gives instruction type. Possible values are :
41
+# - 'column' : add a column
42
+#  - the second tuple item is the SQL type of the new column
43
+#  - the third tuple item is the SQL specs (constraints like default value, nullable, unique , auto_increment etc.)
44
+# - 'table' : add a column in another table and make a fk to the current table
45
+#  - the second tuple item is a tuple(key_name, key_value)
46
+#  - the third tuple item is a tuple(column_type, column_spec)
47
+# @param fieldtype GenericFieldType : A FieldType instance
48
+# @return a tuple (instruction_type, infos)
49
+def fieldtype_db_init(fieldtype):
50
+    if isinstance(fieldtype, EditorialModel.fieldtypes.rel2type.EmFieldType):
51
+        return (None, None, None)
52
+    elif isinstance(fieldtype, SingleValueFieldType):
53
+        res = [ 'column', None, singlevaluefieldtype_db_init_specs(fieldtype) ]
54
+        # We will create a column
55
+        if isinstance(fieldtype, EditorialModel.fieldtypes.integer.EmFieldType):
56
+            res[1] = 'INT'
57
+        elif isinstance(fieldtype, EditorialModel.fieldtypes.char.EmFieldType):
58
+            res[1] = 'VARCHAR(%d)' % fieldtype.max_length
59
+        elif isinstance(fieldtype, EditorialModel.fieldtypes.text.EmFieldType):
60
+            res[1] = 'TEXT'
61
+        elif isinstance(fieldtype, EditorialModel.fieldtypes.bool.EmFieldType):
62
+            res[1] = 'BOOL'
63
+        elif isinstance(fieldtype, EditorialModel.fieldtypes.datetime.EmFieldType):
64
+            res[1] = 'DATETIME'
65
+        elif isinstance(fieldtype, EditorialModel.fieldtypes.generic.ReferenceFieldType):
66
+            res[1] = 'INT'
67
+        else:
68
+            raise RuntimeError("Unsupported fieldtype : ", fieldtype)
69
+        return tuple(res)
70
+    elif isinstance(fieldtype, MultiValueFieldType):
71
+        res = [ 'table', None, None ]
72
+        key_type, _ = fieldtype_db_init(fieldtype.key_fieldtype)
73
+        key_name = fieldtype.keyname
74
+        res[1] = (key_name, key_type)
75
+        res[2] = fieldtype_db_init(fieldtype.value_fieldtype)
76
+    else:
77
+        raise NotImplementedError("Not yet implemented")
78
+            
79
+    
80
+

+ 39
- 67
DataSource/MySQL/migrationhandler.py View File

@@ -10,6 +10,7 @@ import EditorialModel.classtypes
10 10
 import EditorialModel.fieldtypes
11 11
 import EditorialModel.fieldtypes.generic
12 12
 
13
+from DataSource.MySQL import fieldtypes as fieldtypes_utils
13 14
 from DataSource.MySQL import utils
14 15
 from DataSource.dummy.migrationhandler import DummyMigrationHandler
15 16
 
@@ -274,8 +275,6 @@ class MysqlMigrationHandler(DummyMigrationHandler):
274 275
 
275 276
         # Creating foreign keys between relation and object table
276 277
         sup_cname, sub_cname = self.get_sup_and_sub_cols()
277
-        self._add_fk(tname, object_tname, sup_cname, self._object_pk[0], 'fk_relations_superiors')
278
-        self._add_fk(tname, object_tname, sub_cname, self._object_pk[0], 'fk_relations_subordinate')
279 278
 
280 279
     ## @brief Returns the fieldname for superior and subordinate in relation table
281 280
     # @return a tuple (superior_name, subordinate_name)
@@ -301,8 +300,9 @@ class MysqlMigrationHandler(DummyMigrationHandler):
301 300
     def _create_table(self, table_name, pk_name, pk_ftype, engine, charset='utf8', if_exists='nothing'):
302 301
         #Escaped table name
303 302
         etname = utils.escape_idname(table_name)
304
-        pk_type = self._field_to_type(pk_ftype)
305
-        pk_specs = self._field_to_specs(pk_ftype)
303
+        instr_type, pk_type, pk_specs = fieldtypes_utils.fieldtype_db_init(pk_ftype)
304
+        if instr_type != 'column':
305
+            raise ValueError("Migration handler doesn't support MultiValueFieldType as primary keys")
306 306
 
307 307
         if if_exists == 'drop':
308 308
             self._query("""DROP TABLE IF EXISTS {table_name};""".format(table_name=etname))
@@ -343,11 +343,17 @@ ADD COLUMN {col_name} {col_type} {col_specs};"""
343 343
         etname = utils.escape_idname(table_name)
344 344
         ecname = utils.escape_idname(col_name)
345 345
 
346
+        instr, col_type, col_specs = fieldtypes_utils.fieldtype_db_init(col_fieldtype)
347
+        if instr is None:
348
+            return True
349
+        if instr != "column":
350
+            raise RuntimeError("Bad implementation")
351
+
346 352
         add_col = add_col.format(
347 353
             table_name=etname,
348 354
             col_name=ecname,
349
-            col_type=self._field_to_type(col_fieldtype),
350
-            col_specs=self._field_to_specs(col_fieldtype),
355
+            col_type=col_type,
356
+            col_specs=col_specs,
351 357
         )
352 358
         try:
353 359
             self._query(add_col)
@@ -359,6 +365,31 @@ ADD COLUMN {col_name} {col_type} {col_specs};"""
359 365
                 #LOG
360 366
                 print("Aborded, column `%s` exists" % col_name)
361 367
                 return False
368
+
369
+        if isinstance(col_fieldtype, EditorialModel.fieldtypes.generic.ReferenceFieldType):
370
+            # We have to create a FK !
371
+            if col_fieldtype.reference == 'object':
372
+                dst_table_name = utils.common_tables['object']
373
+                dst_col_name, _ = self._object_pk
374
+            elif col_fieldtypes.reference == 'relation':
375
+                dst_table_name = utils.common_tables['relation']
376
+                dst_col_name, _ = self._relation_pk
377
+            
378
+            fk_name = 'fk_%s-%s_%s-%s' % (
379
+                                            table_name,
380
+                                            col_name,
381
+                                            dst_table_name,
382
+                                            dst_col_name,
383
+                                        )
384
+                
385
+            self._add_fk(
386
+                            src_table_name = table_name,
387
+                            dst_table_name = dst_table_name,
388
+                            src_col_name = col_name,
389
+                            dst_col_name = dst_col_name,
390
+                            fk_name = fk_name
391
+                        )
392
+
362 393
         return True
363 394
 
364 395
     ## @brief Add a foreign key
@@ -398,7 +429,7 @@ FOREIGN KEY ({src_col}) references {dst_table}({dst_col});""".format(
398 429
             self._query("""ALTER TABLE {src_table}
399 430
 DROP FOREIGN KEY {fk_name}""".format(
400 431
     src_table=utils.escape_idname(src_table_name),
401
-    fk_name=fk_name
432
+    fk_name=utils.escape_idname(fk_name)
402 433
 ))
403 434
         except self._dbmodule.err.InternalError:
404 435
             # If the FK don't exists we do not care
@@ -412,7 +443,7 @@ DROP FOREIGN KEY {fk_name}""".format(
412 443
         colval_l_ins = dict()  # param for insert trigger
413 444
 
414 445
         for cname, cftype in cols_ftype.items():
415
-            if cftype.ftype == 'datetime':
446
+            if isinstance(cftype, EditorialModel.fieldtypes.datetime.EmFieldType):
416 447
                 if cftype.now_on_update:
417 448
                     colval_l_upd[cname] = 'NOW()'
418 449
                 if cftype.now_on_create:
@@ -450,65 +481,6 @@ FOR EACH ROW SET {col_val_list};""".format(
450 481
 )
451 482
             self._query(trig_q)
452 483
 
453
-    ## @brief Identifier escaping
454
-    # @param idname str : An SQL identifier
455
-    #def _idname_escape(self, idname):
456
-    #    if '`' in idname:
457
-    #        raise ValueError("Invalid name : '%s'"%idname)
458
-    #    return '`%s`'%idname
459
-
460
-    ## @brief Returns column specs from fieldtype
461
-    # @param emfieldtype EmFieldType : An EmFieldType insance
462
-    # @todo escape default value
463
-    def _field_to_specs(self, emfieldtype):
464
-        colspec = ''
465
-        if not emfieldtype.nullable:
466
-            colspec = 'NOT NULL'
467
-        if hasattr(emfieldtype, 'default'):
468
-            colspec += ' DEFAULT '
469
-            if emfieldtype.default is None:
470
-                colspec += 'NULL '
471
-            else:
472
-                colspec += emfieldtype.default  # ESCAPE VALUE HERE !!!!
473
-
474
-        if emfieldtype.name == 'pk':
475
-            colspec += ' AUTO_INCREMENT'
476
-
477
-        return colspec
478
-
479
-    ## @brief Given a fieldtype return a MySQL type specifier
480
-    # @param emfieldtype EmFieldType : A fieldtype
481
-    # @return the corresponding MySQL type
482
-    def _field_to_type(self, emfieldtype):
483
-        ftype = emfieldtype.ftype
484
-
485
-        if ftype == 'char' or ftype == 'str':
486
-            res = "VARCHAR(%d)" % emfieldtype.max_length
487
-        elif ftype == 'text':
488
-            res = "TEXT"
489
-        elif ftype == 'datetime':
490
-            res = "DATETIME"
491
-            # client side workaround for only one column with CURRENT_TIMESTAMP : giving NULL to timestamp that don't allows NULL
492
-            # cf. https://dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html#idm139961275230400
493
-            # The solution for the migration handler is to create triggers :
494
-            # CREATE TRIGGER trigger_name BEFORE INSERT ON `my_super_table`
495
-            # FOR EACH ROW SET NEW.my_date_column = NOW();
496
-            # and
497
-            # CREATE TRIGGER trigger_name BEFORE UPDATE ON
498
-
499
-        elif ftype == 'bool':
500
-            res = "BOOL"
501
-        elif ftype == 'int':
502
-            res = "INT"
503
-        elif ftype == 'rel2type':
504
-            res = "INT"
505
-        elif ftype == 'leobject':
506
-            res = "INT"
507
-        else:
508
-            raise ValueError("Unsuported fieldtype ftype : %s" % ftype)
509
-
510
-        return res
511
-
512 484
     ## @brief Delete all table created by the MH
513 485
     # @param model Model : the Editorial model
514 486
     def __purge_db(self, model):

+ 3
- 5
EditorialModel/fieldtypes/char.py View File

@@ -1,17 +1,15 @@
1 1
 #-*- coding: utf-8 -*-
2 2
 
3
-from .generic import GenericFieldType
3
+from .generic import SingleValueFieldType
4 4
 
5 5
 
6
-class EmFieldType(GenericFieldType):
6
+class EmFieldType(SingleValueFieldType):
7 7
 
8 8
     help = 'Basic string (varchar) field. Take max_length=64 as option'
9 9
 
10
-    ftype = 'char'
11
-
12 10
     ## @brief A char field
13 11
     # @brief max_length int : The maximum length of this field
14 12
     def __init__(self, max_length=64, **kwargs):
15 13
         self.max_length = max_length
16
-        super(EmFieldType, self).__init__(ftype='char', **kwargs)
14
+        super(EmFieldType, self).__init__(**kwargs)
17 15
 

+ 3
- 5
EditorialModel/fieldtypes/datetime.py View File

@@ -1,14 +1,12 @@
1 1
 #-*- coding: utf-8 -*-
2 2
 
3
-from .generic import GenericFieldType
3
+from .generic import SingleValueFieldType
4 4
 
5 5
 
6
-class EmFieldType(GenericFieldType):
6
+class EmFieldType(SingleValueFieldType):
7 7
 
8 8
     help = 'A datetime field. Take two boolean options now_on_update and now_on_create'
9 9
 
10
-    ftype = 'datetime'
11
-
12 10
     ## @brief A datetime field
13 11
     # @param now_on_update bool : If true the date is set to NOW on update
14 12
     # @param now_on_create bool : If true the date is set to NEW on creation
@@ -16,4 +14,4 @@ class EmFieldType(GenericFieldType):
16 14
     def __init__(self, now_on_update=False, now_on_create=False, **kwargs):
17 15
         self.now_on_update = now_on_update
18 16
         self.now_on_create = now_on_create
19
-        super(EmFieldType, self).__init__(ftype='datetime', **kwargs)
17
+        super(EmFieldType, self).__init__(**kwargs)

+ 1
- 1
EditorialModel/fieldtypes/emuid.py View File

@@ -13,7 +13,7 @@ class EmFieldType(integer.EmFieldType):
13 13
     def __init__(self, is_id_class, **kwargs):
14 14
         self._is_id_class = is_id_class
15 15
         kwargs['internal'] = 'automatic'
16
-        super(EmFieldType, self).__init__(is_id_class = is_id_class, **kwargs)
16
+        super().__init__(is_id_class = is_id_class, **kwargs)
17 17
 
18 18
     def _check_data_value(self, value):
19 19
         return (value, None)

+ 101
- 78
EditorialModel/fieldtypes/generic.py View File

@@ -3,80 +3,44 @@
3 3
 import types
4 4
 import importlib
5 5
 
6
-
7
-## @brief Abstract class representing a fieldtype
8
-# 
9
-# Important notes on datas checking :
10 6
 class GenericFieldType(object):
7
+    
8
+    help_text = 'Generic field type : abstract class for every fieldtype'
11 9
 
12
-    ## @brief Text describing the fieldtype
13
-    help = 'Generic field type : abstract class for every fieldtype'
14
-    ## @brief Allowed type for handled datas
15
-    _allowed_ftype = ['char', 'str', 'int', 'bool', 'datetime', 'text', 'rel2type', 'leobject']
16
-
17
-    ## @brief The basic lowlevel value type
18
-    ftype = None
19
-
20
-    ## @brief Instanciate a new fieldtype
21
-    # @param ftype str : The type of datas handled by this fieldtype
22
-    # @param nullable bool : is None allowed as value ?
23
-    # @param check_function function : A callback check function that takes 1 argument and raise a TypeError if the validation fails
24
-    # @param uniq bool : Indicate if a field should handle uniq values
25
-    # @param primary bool : If true the field is a primary key
26
-    # @param **kwargs dict : Other arguments
27
-    # @throw NotImplementedError if called directly
28
-    # @throw AttributeError if bad ftype
29
-    # @throw AttributeError if bad check_function
30
-    def __init__(self, ftype, nullable=True, check_data_value=None, uniq=False, primary=False, **kwargs):
10
+    ## @param internal False | str : define wheter or not a field is internal
11
+    # @throw NotImplementedError if called from bad class
12
+    def __init__(self, internal = False, **args):
31 13
         if self.__class__ == GenericFieldType:
32 14
             raise NotImplementedError("Abstract class")
33
-
34
-        if self.ftype is None:
35
-            raise RuntimeError("The class attribute ftype is not properly set by the %s EmFieldType" % self.name)
36
-
37
-        if ftype not in self._allowed_ftype:
38
-            raise AttributeError("Ftype '%s' not known" % ftype)
39
-
40
-        if ftype != self.__class__.ftype:
41
-            raise RuntimeError("The ftype is not the same for the instance and the class. Maybe %s reimplement ftype at class level but shouldn't" % self.name)
42
-
43
-        self.ftype = ftype
44
-        self.nullable = bool(nullable)
45
-        self.uniq = bool(uniq)
46
-
47
-        if 'default' in kwargs:
48
-            self.default, error = self.check_data_value(kwargs['default'])
49
-            if error:
50
-                raise error
51
-            del kwargs['default']
52
-
53
-        for argname, argvalue in kwargs.items():
54
-            setattr(self, argname, argvalue)
55
-
56
-    ## @return A fieldtype name from an instance
15
+        self.internal = internal #Check this value ?
16
+    
17
+        for argname, argval in args.items():
18
+            setattr(self, argname, argval)
19
+    
20
+    ## Fieldtype name
21
+    # @todo should be a staticmethod
57 22
     @property
58 23
     def name(self):
59 24
         return self.__module__.split('.')[-1]
60 25
     
61
-    ## @return True if a field is internal, else returns False
26
+    ## @return True if a fieldtype is internal
62 27
     def is_internal(self):
63
-        return hasattr(self, 'internal') and self.internal
64
-
65
-    ## @brief Check if a Value is correct else return a check fail reason
66
-    # @param value * : The value to check
67
-    # @return (checked_and_casted_value, Exception|None)
28
+        return self.internal != False
29
+    
30
+    ## @brief Take care to call the fieldtype defined _check_data_value() method
31
+    # @return a tuple (value, error|None)
68 32
     def check_data_value(self, value):
69
-        if value is None:
70
-            if not self.nullable:
71
-                return (None, TypeError("'None' value but field is not nullable"))
72
-            return (None, None)
73 33
         return self._check_data_value(value)
34
+
35
+    def _check_data_value(self, value):
36
+        return (value, None)
74 37
     
75
-    ## @brief Build automatic fields values
38
+    ## @brief Build field value
76 39
     # @param lec LeCrud : A LeCrud child class
77
-    # @param fname str : The field name
78
-    # @param datas dict : dict storing fields values
79
-    # @return constructed datas
40
+    # @param fname str : The field name
41
+    # @param datas dict : dict storing fields values (from the lec)
42
+    # @return constructed datas (for the fname field)
43
+    # @throw RuntimeError if unable to construct data
80 44
     def construct_data(self, lec, fname, datas):
81 45
         if fname in datas:
82 46
             return datas[fname]
@@ -85,7 +49,7 @@ class GenericFieldType(object):
85 49
         elif lec.fieldtypes()[fname].nullable:
86 50
             return None
87 51
         raise RuntimeError("Unable to construct data for field %s", fname)
88
-    
52
+
89 53
     ## @brief Check datas consistency
90 54
     # @param leo LeCrud : A LeCrud child class instance
91 55
     # @param fname str : The field name
@@ -94,12 +58,6 @@ class GenericFieldType(object):
94 58
     def check_data_consistency(self, lec, fname, datas):
95 59
         return True
96 60
 
97
-    ## @brief Dummy check, designed to be implemented in child classes
98
-    # @param value * : The value
99
-    # @return (checked_and_casted_value, Exception|None)
100
-    def _check_data_value(self, value):
101
-        return (value, None)
102
-
103 61
     ## @brief Given a fieldtype name return the associated python class
104 62
     # @param fieldtype_name str : A fieldtype name
105 63
     # @return An GenericFieldType derivated class
@@ -122,18 +80,83 @@ class GenericFieldType(object):
122 80
             hash_dats.append((kdic, getattr(self, kdic)))
123 81
         return hash(tuple(hash_dats))
124 82
 
125
-    ## @brief Transform a value into a valid python representation according to the fieldtype
126
-    # @param value ? : The value to cast
127
-    # @param kwargs dict : optionnal cast arguments
128
-    # @return Something (depending on the fieldtype
129
-    # @throw AttributeError if error in argument given to the method
130
-    # @throw TypeError if the cast is not possible
131
-    def cast(self, value, **kwargs):
132
-        if len(kwargs) > 0:
133
-            raise AttributeError("No optionnal argument allowed for %s cast method" % self.__class__.__name__)
134
-        return value
83
+class SingleValueFieldType(GenericFieldType):
84
+    
85
+    ## @brief Instanciate a new fieldtype
86
+    # @param nullable bool : is None allowed as value ?
87
+    # @param uniqu bool : Indicate if a field should handle uniq value
88
+    # @param primary bool : If True the field is a primary key
89
+    # @param **args : Other arguments
90
+    # @throw NotImplementedError if called from bad class
91
+    def __init__(self, internal = False, nullable = True, uniq = False, primary = False, **args):
92
+        if self.__class__ == SingleValueFieldType:
93
+            raise NotImplementedError("Asbtract class")
94
+
95
+        super().__init__(internal, **args)
96
+
97
+        self.nullable = nullable
98
+        self.uniq = uniq
99
+        self.primary = primary
100
+        if 'default' in args:
101
+            self.default, error = self.check_data_value(args['default'])
102
+            if error:
103
+                raise error
104
+            del(args['default'])
135 105
 
106
+    def check_data_value(self, value):
107
+        if value is None:
108
+            if not self.nullable:
109
+                return (None, TypeError("'None' value but field is not nullable"))
110
+            return (None, None)
111
+        return super().check_data_value(value)
112
+
113
+class ReferenceFieldType(SingleValueFieldType):
136 114
 
115
+    ## @brief Instanciate a new fieldtype
116
+    #
117
+    #
118
+    # @param reference str : A string that defines the reference (can be 'object' or 'relation')
119
+    # @param nullable bool : is None allowed as value ?
120
+    # @param unique bool : Indicate if a field should handle uniq value
121
+    # @param primary bool : If True the field is a primary key
122
+    # @param **args : Other arguments
123
+    # @throw NotImplementedError if called from bad class
124
+    def __init__(self, reference, internal=False, nullable = True, uniq = False, primary = False, **args):
125
+        if reference.lower() not in ['relation', 'object']:
126
+            raise ValueError("Bad value for reference : %s. Excepted on of 'relation', 'object'" % reference)
127
+        self.reference = reference.lower()
128
+        super().__init__(
129
+                            internal = internal,
130
+                            nullable = nullable,
131
+                            uniq = uniq,
132
+                            primary = primary,
133
+                            **args
134
+        );
135
+        pass
136
+
137
+class MultiValueFieldType(GenericFieldType):
138
+    
139
+    ## @brief Instanciate a new multivalue fieldtype
140
+    #
141
+    # This fieldtype describe a field that handles multiple values referenced by a key (like a dict).
142
+    # A typicall example is the i18n fieldtype
143
+    # @param keyname str : The identifier key name
144
+    # @param key_fieldtype SingleValueFieldType : A SingleValueFieldType child class instance
145
+    # @param value_fieldtype SingleValueFieldType : A SingleValueFieldType child class instance
146
+    def __init__(self, internal, keyname, key_fieldtype, value_fieldtype, **args):
147
+        super().__init__(internal)
148
+        ## stores the keyname
149
+        self.keyname = keyname
150
+        ## stores the fieldtype that handles the key
151
+        self.key_fieldtype = key_fieldtype
152
+        ## stores the fieldtype that handles the values
153
+        self.value_fieldtype = value_fieldtype
154
+
155
+#
156
+#
157
+#   Exceptions
158
+#
159
+#
137 160
 class FieldTypeError(Exception):
138 161
     pass
139 162
 

+ 2
- 2
EditorialModel/fieldtypes/integer.py View File

@@ -1,9 +1,9 @@
1 1
 #-*- coding: utf-8 -*-
2 2
 
3
-from .generic import GenericFieldType
3
+from .generic import SingleValueFieldType
4 4
 
5 5
 
6
-class EmFieldType(GenericFieldType):
6
+class EmFieldType(SingleValueFieldType):
7 7
 
8 8
     help = 'Basic integer field'
9 9
 

+ 5
- 4
EditorialModel/fieldtypes/leo.py View File

@@ -3,16 +3,17 @@
3 3
 import leapi.letype as letype
4 4
 import leapi.leclass as leclass
5 5
 
6
-from .generic import GenericFieldType, FieldTypeError
6
+from .generic import ReferenceFieldType, FieldTypeError
7 7
 
8
-class EmFieldType(GenericFieldType):
8
+class EmFieldType(ReferenceFieldType):
9 9
     
10 10
     help = 'Fieldtypes designed to handle pk of LeObject in LeRelations'
11 11
 
12 12
     ftype = 'leobject'
13
-
13
+    
14
+    ## @todo Replace hardcoded string for reference initialisation
14 15
     def __init__(self, superior=True, **kwargs):
15
-        super(EmFieldType, self).__init__(ftype = 'leobject', superior = superior, **kwargs)
16
+        super().__init__(superior = superior, reference='object', **kwargs)
16 17
 
17 18
     def _check_data_value(self, value):
18 19
         if not isinstance(value, int):

+ 3
- 3
EditorialModel/fieldtypes/naturerelation.py View File

@@ -10,10 +10,10 @@ class EmFieldType(EmFieldType):
10 10
     help = 'Stores a relation\'s nature'
11 11
 
12 12
     def __init__(self, **kwargs):
13
-        kwargs.update({'nullable': True, 'check_data_value': EmFieldType.check_data_value})
14
-        super(EmFieldType, self).__init__(**kwargs)
13
+        kwargs.update({'nullable': True})
14
+        super().__init__(**kwargs)
15 15
 
16
-    def check_data_value(self, value):
16
+    def _check_data_value(self, value):
17 17
         if value is None or ( value in classtypes.EmNature.getall()):
18 18
             return value, None
19 19
         else:

+ 1
- 1
EditorialModel/fieldtypes/rel2type.py View File

@@ -12,7 +12,7 @@ class EmFieldType(GenericFieldType):
12 12
 
13 13
     def __init__(self, rel_to_type_id, **kwargs):
14 14
         self.rel_to_type_id = rel_to_type_id
15
-        super(EmFieldType, self).__init__(ftype='rel2type', **kwargs)
15
+        super(EmFieldType, self).__init__(**kwargs)
16 16
 
17 17
     def get_related_type(self):
18 18
         return self.model.component(self.rel_to_type_id)

Loading…
Cancel
Save