Няма описание
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #-*- coding: utf-8 -*-
  2. import copy
  3. import importlib
  4. import warnings
  5. from EditorialModel.components import EmComponent
  6. from EditorialModel.exceptions import EmComponentCheckError
  7. from EditorialModel.fieldtypes.generic import GenericFieldType
  8. import EditorialModel
  9. import EditorialModel.fieldtypes
  10. #from django.db import models
  11. ## EmField (Class)
  12. #
  13. # Represents one data for a lodel2 document
  14. class EmField(EmComponent):
  15. ranked_in = 'class_id'
  16. ## Instanciate a new EmField
  17. # @todo define and test type for icon
  18. # @warning nullable == True by default
  19. # @param model Model : Editorial model
  20. # @param uid int : Uniq id
  21. # @param fieldtype str : Fieldtype name ( see Editorialmodel::fieldtypes )
  22. # @param optional bool : Indicate if a field is optional or not
  23. # @param internal str|bool : If False the field is not internal, else it can takes value in "object" or "automatic"
  24. # @param rel_field_id int|None : If not None indicates that the field is a relation attribute (and the value is the UID of the rel2type field)
  25. # @param nullable bool : If True None values are allowed
  26. # @param uniq bool : if True the value should be uniq in the db table
  27. # @param **kwargs : more keywords arguments for the fieldtype
  28. def __init__(self, model, uid, name, class_id, fieldtype, optional=False, internal=False, rel_field_id=None, icon='0', string=None, help_text=None, date_update=None, date_create=None, rank=None, nullable=False, uniq=False, **kwargs):
  29. self.class_id = class_id
  30. self.check_type('class_id', int)
  31. self.optional = bool(optional)
  32. if not internal:
  33. self.internal = False
  34. else:
  35. if internal.lower() not in ['automatic', 'autosql']:
  36. raise ValueError("The internal arguments possible values are : [False, 'autosql', 'automatic']")
  37. self.internal = internal.lower()
  38. if self.internal == 'object' and name not in EditorialModel.classtypes.common_fields.keys():
  39. raise ValueError("Only common_fields are allowed to have the argument internal='object'")
  40. self.rel_field_id = rel_field_id
  41. self.check_type('rel_field_id', (int, type(None)))
  42. self.icon = icon
  43. #Field type elements
  44. self._fieldtype_cls = GenericFieldType.from_name(fieldtype)
  45. self.fieldtype = fieldtype
  46. self._fieldtype_args = kwargs
  47. self._fieldtype_args.update({'nullable': nullable, 'uniq': uniq, 'internal': self.internal})
  48. try:
  49. fieldtype_instance = self._fieldtype_cls(**self._fieldtype_args)
  50. except AttributeError as e:
  51. raise AttributeError("Error will instanciating fieldtype : %s" % e)
  52. if 'default' in kwargs:
  53. if not fieldtype_instance.check(default):
  54. raise TypeError("Default value ('%s') is not valid given the fieldtype '%s'" % (default, fieldtype))
  55. self.nullable = nullable
  56. self.uniq = uniq
  57. for kname, kval in kwargs.items():
  58. setattr(self, kname, kval)
  59. super(EmField, self).__init__(model=model, uid=uid, name=name, string=string, help_text=help_text, date_update=date_update, date_create=date_create, rank=rank)
  60. @staticmethod
  61. ## @brief Return the list of allowed field type
  62. def fieldtypes_list():
  63. return [f for f in EditorialModel.fieldtypes.__all__ if f != '__init__' and f != 'generic']
  64. ##@brief Return the EmFieldgroup this EmField belongs to
  65. @property
  66. def _fieldgroup(self):
  67. return self.model.component(self.fieldgroup_id)
  68. ## @brief Returns the EmClass this EmField belongs to
  69. @property
  70. def em_class(self):
  71. return self.model.component(self.class_id)
  72. ## @brief Getter for private property EmField._fieldtype_args
  73. # @return A copy of private dict _fieldtype_args
  74. def fieldtype_options(self):
  75. return copy.copy(self._fieldtype_args)
  76. ## @brief Get the fieldtype instance
  77. # @return a fieldtype instance
  78. def fieldtype_instance(self):
  79. return self._fieldtype_cls(**self._fieldtype_args)
  80. ## @brief Return the list of relation fields for a rel_to_type
  81. # @return None if the field is not a rel_to_type else return a list of EmField
  82. def rel_to_type_fields(self):
  83. if not self.rel_to_type_id: # TODO Ajouter cette propriété
  84. return None
  85. return [f for f in self.model.components(EmField) if f.rel_field_id == self.uid]
  86. ## Check if the EmField is valid
  87. #
  88. # Check multiple things :
  89. # - the fieldgroup_id is valid
  90. # - the name is uniq in the EmClass
  91. # - if its a rel2type check that the linked_type is uniq in the EmClass
  92. # @return True if valid False if not
  93. def check(self):
  94. super(EmField, self).check()
  95. """
  96. #Fieldgroup check
  97. em_fieldgroup = self.model.component(self.fieldgroup_id)
  98. if not em_fieldgroup:
  99. raise EmComponentCheckError("fieldgroup_id contains a non existing uid : '%d'" % self.fieldgroup_id)
  100. if not isinstance(em_fieldgroup, EditorialModel.fieldgroups.EmFieldGroup):
  101. raise EmComponentCheckError("fieldgroup_id contains an uid from a component that is not an EmFieldGroup but a %s" % str(type(em_fieldgroup)))
  102. """
  103. #Uniq Name check
  104. if len([f for f in self.em_class.fields() if f.name == self.name]) > 1:
  105. raise EmComponentCheckError("The field %d has a name '%s' that is not uniq in the EmClass %d" % (self.uid, self.name, self.em_class.uid))
  106. #rel2type uniq check
  107. if self.fieldtype == 'rel2type':
  108. if len([f for f in self.em_class.fields() if f.fieldtype == 'rel2type' and f.rel_to_type_id == self.rel_to_type_id]) > 1:
  109. raise EmComponentCheckError("The rel2type %d is not uniq, another field is linked to the same type '%s' in the same class '%s'" % (self.uid, self.model.component(self.rel_to_type_id).name, self.em_class.name))
  110. ## @brief Delete a field if it's not linked
  111. # @return bool : True if deleted False if deletion aborded
  112. # @todo Check if unconditionnal deletion is correct
  113. def delete_check(self):
  114. return True