mirror of
https://github.com/yweber/lodel2.git
synced 2026-04-02 08:57:15 +02:00
Implements order in fieldtype construct
This commit is contained in:
parent
03ab4b0c59
commit
1daf9677c6
5 changed files with 83 additions and 30 deletions
|
|
@ -10,6 +10,8 @@ class EmFieldType(integer.EmFieldType):
|
||||||
|
|
||||||
help = 'Fieldtypes designed to handle editorial model UID for LeObjects'
|
help = 'Fieldtypes designed to handle editorial model UID for LeObjects'
|
||||||
|
|
||||||
|
_construct_datas_deps = []
|
||||||
|
|
||||||
def __init__(self, is_id_class, **kwargs):
|
def __init__(self, is_id_class, **kwargs):
|
||||||
self._is_id_class = is_id_class
|
self._is_id_class = is_id_class
|
||||||
kwargs['internal'] = 'automatic'
|
kwargs['internal'] = 'automatic'
|
||||||
|
|
@ -18,18 +20,15 @@ class EmFieldType(integer.EmFieldType):
|
||||||
def _check_data_value(self, value):
|
def _check_data_value(self, value):
|
||||||
return (value, None)
|
return (value, None)
|
||||||
|
|
||||||
def construct_data(self, lec, fname, datas):
|
def _construct_data(self, lec, fname, datas, cur_value):
|
||||||
|
ret = None
|
||||||
if self.is_id_class:
|
if self.is_id_class:
|
||||||
if lec.implements_leclass():
|
if lec.implements_leclass():
|
||||||
datas[fname] = lec._class_id
|
ret = lec._class_id
|
||||||
else:
|
|
||||||
datas[fname] = None
|
|
||||||
else:
|
else:
|
||||||
if lec.implements_letype():
|
if lec.implements_letype():
|
||||||
datas[fname] = lec._type_id
|
ret = lec._type_id
|
||||||
else:
|
return ret
|
||||||
datas[fname] = None
|
|
||||||
return datas[fname]
|
|
||||||
|
|
||||||
def check_data_consistency(self, lec, fname, datas):
|
def check_data_consistency(self, lec, fname, datas):
|
||||||
if datas[fname] != (lec._class_id if self.is_id_class else lec._type_id):
|
if datas[fname] != (lec._class_id if self.is_id_class else lec._type_id):
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
#-*- coding: utf-8 -*-
|
#-*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import copy
|
||||||
import types
|
import types
|
||||||
import importlib
|
import importlib
|
||||||
|
|
||||||
class GenericFieldType(object):
|
class GenericFieldType(object):
|
||||||
|
|
||||||
help_text = 'Generic field type : abstract class for every fieldtype'
|
help_text = 'Generic field type : abstract class for every fieldtype'
|
||||||
|
|
||||||
|
## @brief List fields that will be exposed to the construct_data_method
|
||||||
|
_construct_datas_deps = []
|
||||||
|
|
||||||
## @param internal False | str : define wheter or not a field is internal
|
## @param internal False | str : define wheter or not a field is internal
|
||||||
# @throw NotImplementedError if called from bad class
|
# @throw NotImplementedError if called from bad class
|
||||||
|
|
@ -35,15 +39,22 @@ class GenericFieldType(object):
|
||||||
def _check_data_value(self, value):
|
def _check_data_value(self, value):
|
||||||
return (value, None)
|
return (value, None)
|
||||||
|
|
||||||
|
## @brief Wrapper for _construct_data() method
|
||||||
|
#
|
||||||
|
# Now useless
|
||||||
|
def construct_data(self, lec, fname, datas, cur_value):
|
||||||
|
return self._construct_data(lec, fname, datas, cur_value)
|
||||||
|
|
||||||
## @brief Build field value
|
## @brief Build field value
|
||||||
# @param lec LeCrud : A LeCrud child class
|
# @param lec LeCrud : A LeCrud child class
|
||||||
# @param fname str : The field name
|
# @param fname str : The field name
|
||||||
# @param datas dict : dict storing fields values (from the lec)
|
# @param datas dict : dict storing fields values (from the lec)
|
||||||
|
# @param cur_value : the value for the current field (identified by fieldname)
|
||||||
# @return constructed datas (for the fname field)
|
# @return constructed datas (for the fname field)
|
||||||
# @throw RuntimeError if unable to construct data
|
# @throw RuntimeError if unable to construct data
|
||||||
def construct_data(self, lec, fname, datas):
|
def _construct_data(self, lec, fname, datas, cur_value):
|
||||||
if fname in datas:
|
if fname in datas.keys():
|
||||||
return datas[fname]
|
return cur_value
|
||||||
elif hasattr(lec.fieldtypes()[fname], 'default'):
|
elif hasattr(lec.fieldtypes()[fname], 'default'):
|
||||||
return lec.fieldtypes()[fname].default
|
return lec.fieldtypes()[fname].default
|
||||||
elif lec.fieldtypes()[fname].nullable:
|
elif lec.fieldtypes()[fname].nullable:
|
||||||
|
|
@ -152,6 +163,41 @@ class MultiValueFieldType(GenericFieldType):
|
||||||
## stores the fieldtype that handles the values
|
## stores the fieldtype that handles the values
|
||||||
self.value_fieldtype = value_fieldtype
|
self.value_fieldtype = value_fieldtype
|
||||||
|
|
||||||
|
## @brief Class designed to handle datas access will fieldtypes are constructing datas
|
||||||
|
class DatasConstructor(object):
|
||||||
|
|
||||||
|
## @brief Init a DatasConstructor
|
||||||
|
# @param lec LeCrud : LeCrud child class
|
||||||
|
# @param datas dict : dict with field name as key and field values as value
|
||||||
|
# @param fieldtypes dict : dict with field name as key and fieldtype as value
|
||||||
|
def __init__(self, lec, datas, fieldtypes):
|
||||||
|
## Stores concerned class
|
||||||
|
self._lec = lec
|
||||||
|
## Stores datas and constructed datas
|
||||||
|
self._datas = copy.copy(datas)
|
||||||
|
## Stores fieldtypes
|
||||||
|
self._fieldtypes = fieldtypes
|
||||||
|
## Stores list of fieldname for constructed datas
|
||||||
|
self._constructed = []
|
||||||
|
## Stores construct calls list
|
||||||
|
self._construct_calls = []
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
return self._datas.keys()
|
||||||
|
|
||||||
|
def __getitem__(self, fname):
|
||||||
|
if fname not in self._constructed:
|
||||||
|
if fname in self._construct_calls:
|
||||||
|
raise RuntimeError('Probably circular dependencies in fieldtypes')
|
||||||
|
cur_value = self._datas[fname] if fname in self._datas else None
|
||||||
|
self._datas[fname] = self._fieldtypes[fname].construct_data(self._lec, fname, self, cur_value)
|
||||||
|
self._constructed.append(fname)
|
||||||
|
return self._datas[fname]
|
||||||
|
|
||||||
|
def __setitem__(self, fname, value):
|
||||||
|
self._datas[fname] = value
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Exceptions
|
# Exceptions
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ class EmFieldType(ReferenceFieldType):
|
||||||
|
|
||||||
help = 'Fieldtypes designed to handle pk of LeObject in LeRelations'
|
help = 'Fieldtypes designed to handle pk of LeObject in LeRelations'
|
||||||
|
|
||||||
ftype = 'leobject'
|
_construct_data_deps = []
|
||||||
|
|
||||||
## @todo Replace hardcoded string for reference initialisation
|
## @todo Replace hardcoded string for reference initialisation
|
||||||
def __init__(self, superior=True, **kwargs):
|
def __init__(self, superior=True, **kwargs):
|
||||||
|
|
@ -25,23 +25,23 @@ class EmFieldType(ReferenceFieldType):
|
||||||
|
|
||||||
## @brief If field value is an integer, returns a partially instanciated LeObject (only with an ID)
|
## @brief If field value is an integer, returns a partially instanciated LeObject (only with an ID)
|
||||||
# @todo what should we do if the get fails ? Raise ?
|
# @todo what should we do if the get fails ? Raise ?
|
||||||
def construct_data(self, lec, fname, datas):
|
def _construct_data(self, lec, fname, datas, cur_value):
|
||||||
if isinstance(datas[fname], str):
|
if isinstance(cur_value, str):
|
||||||
# Cast to int
|
# Cast to int
|
||||||
try:
|
try:
|
||||||
datas[fname] = int(datas[fname])
|
cur_value = int(cur_value)
|
||||||
except (ValueError, TypeError) as e:
|
except (ValueError, TypeError) as e:
|
||||||
raise e # Raise Here !?
|
raise e # Raise Here !?
|
||||||
if datas[fname].is_leobject():
|
if cur_value.is_leobject():
|
||||||
# Its an object not populated (we dont now its type)
|
# Its an object not populated (we dont now its type)
|
||||||
datas[fname] = datas[fname].lodel_id #Optimize here giving only class_id and type_id to populate ?
|
cur_value = cur_value.lodel_id #Optimize here giving only class_id and type_id to populate ?
|
||||||
if isinstance(datas[fname], int):
|
if isinstance(cur_value, int):
|
||||||
# Get instance with id
|
# Get instance with id
|
||||||
resget = lec.name2class('LeObject').get(['lodel_id = %d' % datas[fname]])
|
resget = lec.name2class('LeObject').get(['lodel_id = %d' % cur_value])
|
||||||
if resget is None or len(resget) != 1:
|
if resget is None or len(resget) != 1:
|
||||||
# Bad filter or bad id... raise ?
|
# Bad filter or bad id... raise ?
|
||||||
raise Exception("BAAAAAD")
|
raise Exception("BAAAAAD")
|
||||||
return datas[fname]
|
return cur_value
|
||||||
|
|
||||||
## @brief checks datas consistency
|
## @brief checks datas consistency
|
||||||
# @param lec LeCrud : A LeCrud child instance
|
# @param lec LeCrud : A LeCrud child instance
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#-*- coding utf-8 -*-
|
#-*- coding utf-8 -*-
|
||||||
|
|
||||||
|
import EditorialModel.classtypes
|
||||||
import leapi.lerelation as lerelation
|
import leapi.lerelation as lerelation
|
||||||
|
|
||||||
from .generic import FieldTypeError
|
from .generic import FieldTypeError
|
||||||
|
|
@ -9,17 +10,19 @@ class EmFieldType(integer.EmFieldType):
|
||||||
|
|
||||||
help = 'Fieldtype designed to handle relations rank'
|
help = 'Fieldtype designed to handle relations rank'
|
||||||
|
|
||||||
|
_construct_datas_deps = [EditorialModel.classtypes.relation_superior]
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
def construct_data(self, lec, fname, datas):
|
def _construct_data(self, lec, fname, datas, cur_value):
|
||||||
superior_id = datas[lec._superior_field_name]
|
superior_id = datas[EditorialModel.classtypes.relation_superior]
|
||||||
if lec.is_lerel2type():
|
if lec.is_lerel2type():
|
||||||
subordinate = lec._subordinate_cls
|
subordinate = lec._subordinate_cls
|
||||||
sub_em_type_id = subordinate._type_id
|
sub_em_type_id = subordinate._type_id
|
||||||
datas[fname] = lec.get_max_rank(superior_id, sub_em_type_id)
|
cur_value = lec.get_max_rank(superior_id, sub_em_type_id)
|
||||||
elif lec.is_lehierarch():
|
elif lec.is_lehierarch():
|
||||||
datas[fname] = lec.get_max_rank(superior_id, datas['nature'])
|
cur_value = lec.get_max_rank(superior_id, datas['nature'])
|
||||||
else:
|
else:
|
||||||
raise ValueError("Called with bad class : ", lec.__name__)
|
raise ValueError("Called with bad class : ", lec.__name__)
|
||||||
return datas[fname]
|
return cur_value
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ import warnings
|
||||||
import importlib
|
import importlib
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from EditorialModel.fieldtypes.generic import DatasConstructor
|
||||||
|
|
||||||
REL_SUP = 0
|
REL_SUP = 0
|
||||||
REL_SUB = 1
|
REL_SUB = 1
|
||||||
|
|
||||||
|
|
@ -460,11 +462,14 @@ class _LeCrud(object):
|
||||||
# @todo Decide wether or not the datas are modifed inplace or returned in a new dict (second solution for the moment)
|
# @todo Decide wether or not the datas are modifed inplace or returned in a new dict (second solution for the moment)
|
||||||
@classmethod
|
@classmethod
|
||||||
def _construct_datas(cls, datas):
|
def _construct_datas(cls, datas):
|
||||||
res_datas = copy.copy(datas)
|
constructor = DatasConstructor(cls, datas, cls.fieldtypes())
|
||||||
for fname, ftype in cls.fieldtypes().items():
|
ret = {
|
||||||
if not ftype.is_internal() or ftype.internal != 'autosql':
|
fname:constructor[fname]
|
||||||
res_datas[fname] = ftype.construct_data(cls, fname, res_datas)
|
for fname, ftype in cls.fieldtypes().items()
|
||||||
return res_datas
|
if not ftype.is_internal() or ftype.internal != 'autosql'
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
|
||||||
## @brief Check datas consistency
|
## @brief Check datas consistency
|
||||||
#
|
#
|
||||||
# @warning assert that datas is complete
|
# @warning assert that datas is complete
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue