Browse Source

Gestion des relations

prieto 8 years ago
parent
commit
9a66c9a2f6

+ 12
- 5
lodel/leapi/datahandlers/base_classes.py View File

@@ -146,7 +146,7 @@ class DataHandler(object):
146 146
     # @param fieldtype_name str : A field type name (not case sensitive)
147 147
     # @return DataField child class
148 148
     # @todo implements custom handlers fetch
149
-    # @note To access custom data handlers it can be cool to preffix the handler name by plugin name for example ? (to ensure name unicity)
149
+    # @note To access custom data handlers it can be cool to prefix the handler name by plugin name for example ? (to ensure name unicity)
150 150
     @classmethod
151 151
     def from_name(cls, name):
152 152
         cls.load_base_handlers()
@@ -192,12 +192,15 @@ class Reference(DataHandler):
192 192
     # @param **kwargs : other arguments
193 193
     def __init__(self, allowed_classes = None, back_reference = None, internal=False, **kwargs):
194 194
         self.__allowed_classes = [] if allowed_classes is None else set(allowed_classes)
195
+        logger.warning("We're going to inialize an temporary attribute, don't forget to fix this issue")
196
+        self.allowed_classes = None if allowed_classes is None else allowed_classes.pop() ## WARNING : just here for step over the issue with __allowed_classes
195 197
         if back_reference is not None:
196 198
             if len(back_reference) != 2:
197 199
                 raise ValueError("A tuple (classname, fieldname) expected but got '%s'" % back_reference)
198 200
             #if not issubclass(back_reference[0], LeObject) or not isinstance(back_reference[1], str):
199 201
             #    raise TypeError("Back reference was expected to be a tuple(<class LeObject>, str) but got : (%s, %s)" % (back_reference[0], back_reference[1]))
200 202
         self.__back_reference = back_reference
203
+
201 204
         super().__init__(internal=internal, **kwargs)
202 205
     
203 206
     @property
@@ -242,7 +245,7 @@ class SingleRef(Reference):
242 245
         val, expt = super()._check_data_value(value)
243 246
         if not isinstance(expt, Exception):
244 247
             if len(val) > 1:
245
-               return None, FieldValidationError("Only single values are allowed for SingleRef fields")
248
+                return None, FieldValidationError("Only single values are allowed for SingleRef fields")
246 249
         return val, expt
247 250
 
248 251
 
@@ -260,11 +263,15 @@ class MultipleRef(Reference):
260 263
 
261 264
         
262 265
     def _check_data_value(self, value):
263
-        value = value.split(',')
266
+        expt = None
267
+        if isinstance(str, value):
268
+            value, expt = super()._check_data_value(value)
269
+        elif not hasattr(value, '__iter__'):
270
+            return None, FieldValidationError("MultipleRef has to be an iterable or a string")
264 271
         if self.max_item is not None:
265 272
             if self.max_item < len(value):
266
-                return None, FieldValidationError("To many items")
267
-        return value, None
273
+                return None, FieldValidationError("Too many items")
274
+        return value, expt
268 275
 
269 276
 ## @brief Class designed to handle datas access will fieldtypes are constructing datas
270 277
 #

+ 28
- 1
lodel/leapi/datahandlers/references.py View File

@@ -1,6 +1,7 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 from lodel.leapi.datahandlers.base_classes import Reference, MultipleRef, SingleRef, FieldValidationError
3 3
 
4
+from lodel import logger
4 5
 
5 6
 class Link(SingleRef):
6 7
     pass
@@ -20,11 +21,37 @@ class List(MultipleRef):
20 21
     # @param value *
21 22
     # @return tuple(value, exception)
22 23
     def _check_data_value(self, value):
23
-        val, expt = super()._check_data_value(value)
24
+        if isinstance(value, list) or isintance(value, str):
25
+            val, expt = super()._check_data_value(value)
26
+        else:
27
+            return None, FieldValidationError("List or string expected for a list field")
24 28
         if not isinstance(expt, Exception):
25 29
             val = list(val)
26 30
         return val, expt
27 31
 
32
+    def construct_data(self, emcomponent, fname, datas, cur_value):
33
+        emcomponent_fields = emcomponent.fields()
34
+        data_handler = None
35
+        if fname in emcomponent_fields:
36
+            data_handler = emcomponent_fields[fname]
37
+        u_fname = emcomponent.uid_fieldname()
38
+        uidtype = u_fname[0] if isinstance(u_fname, tuple) else u_fname 
39
+        
40
+        if isinstance(cur_value, str):
41
+            value = cur_value.split(',')
42
+            l_value = [uidtype(uid) for uid in value]
43
+            return l_value
44
+        elif isinstance(cur_value, list):
45
+            type_list = str if isinstance(cur_value[0], str) else uidtype
46
+            l_value = list()
47
+            for value in cur_value:
48
+                if isinstance(value,uidtype):
49
+                    l_value.append(value)
50
+                else:
51
+                    raise ValueError("The items must be of the same type, string or %s" % (target.__name__))
52
+            return l_value
53
+        else:
54
+            return None
28 55
 
29 56
 ##@brief Child class of MultipleRef where references are represented in the form of a python set
30 57
 class Set(MultipleRef):

+ 2
- 2
lodel/leapi/leobject.py View File

@@ -499,7 +499,7 @@ DS_PLUGIN_NAME.DS_INSTANCE_NAME. But got %s" % ds_identifier)
499 499
         correct = set() #valid fields name
500 500
         mandatory = set() #mandatory fields name
501 501
         for fname, datahandler in cls._fields.items():
502
-            if allow_internal or not datahandler.is_internal():
502
+            if allow_internal or not datahandler.is_internal() or fname == CLASS_ID_FIELDNAME:
503 503
                 correct.add(fname)
504 504
                 if complete and not hasattr(datahandler, 'default'):
505 505
                     mandatory.add(fname)
@@ -543,7 +543,6 @@ construction and consitency when datas are not complete\n")
543 543
         ret_datas = cls.check_datas_value(datas, complete, allow_internal)
544 544
         if isinstance(ret_datas, Exception):
545 545
             raise ret_datas
546
-
547 546
         if complete:
548 547
             ret_datas = cls._construct_datas(ret_datas)
549 548
             cls._check_datas_consistency(ret_datas)
@@ -563,6 +562,7 @@ construction and consitency when datas are not complete\n")
563 562
                 for fname, ftype in cls._fields.items()
564 563
                 if not ftype.is_internal() or ftype.internal != 'autosql'
565 564
         }
565
+        logger.warning(ret)
566 566
         return ret
567 567
 
568 568
     ## @brief Check datas consistency

+ 3
- 0
plugins/webui/interface/controllers/admin.py View File

@@ -86,6 +86,9 @@ def admin_create(request):
86 86
         for in_put, in_value in request.form.items():
87 87
             if in_put != 'classname':
88 88
                 fields[in_put[12:]] = in_value
89
+            else:
90
+                fields[in_put] = in_value
91
+
89 92
         new_uid = target_leo.insert(fields)
90 93
         
91 94
         if not new_uid is None:

+ 36
- 6
plugins/webui/interface/controllers/listing.py View File

@@ -4,16 +4,46 @@ import leapi_dyncode as dyncode
4 4
 
5 5
 def list_classes(request):
6 6
     template_vars = {'my_classes': dyncode.dynclasses}
7
-    return get_response('listing/list_classes.html', tpl_vars=template_vars)
7
+    return get_response('listing/list_classes.html', my_classes=dyncode.dynclasses)
8 8
 
9 9
 def show_class(request):
10
-    template_vars = {
11
-        'params': request.GET
12
-    }
13
-    return get_response('listing/show_class.html', tpl_vars=template_vars)
10
+    if 'classname' in request.GET:
11
+        classname = request.GET['classname']
12
+        if len(classname) > 1:
13
+            raise HttpException(400)
14
+        classname = classname[0]
15
+        try:
16
+            target_leo = dyncode.Object.name2class(classname)
17
+        except LeApiError:
18
+            classname = None
19
+    return get_response('listing/show_class.html', classname=classname)
14 20
 
15 21
 def show_object(request):
16 22
     template_vars = {
17 23
         'params': request.GET
18 24
     }
19
-    return get_response('listing/show_object.html', tpl_vars=template_vars)
25
+    test_valid = 'lodel_id' in request.GET \
26
+        and len(request.GET['lodel_id']) == 1
27
+
28
+    if test_valid:
29
+        try:
30
+            lodel_id = int(request.GET['lodel_id'][0])
31
+        except (ValueError, TypeError):
32
+            test_valid = False
33
+
34
+    if not test_valid:
35
+        raise HttpException(400)
36
+    else:
37
+        obj = dyncode.Object.get(['lodel_id = %d' % lodel_id])
38
+        if len(obj) == 0:
39
+            raise HttpException(404)
40
+    if 'classname' in request.GET:
41
+        classname = request.GET['classname']
42
+        if len(classname) > 1:
43
+            raise HttpException(400)
44
+        classname = classname[0]
45
+        try:
46
+            target_leo = dyncode.Object.name2class(classname)
47
+        except LeApiError:
48
+            classname = None
49
+    return get_response('listing/show_object.html', lodel_id=lodel_id, classname=classname)

+ 2
- 0
plugins/webui/templates/admin/editable_component.html View File

@@ -4,6 +4,8 @@
4 4
 		<input id="field_input_{{fieldname}}" name="field_input_{{fieldname}}" type="checkbox" checked="{% if value %}checked{% endif %}" />
5 5
 	{% elif field.base_type == 'char' or field.base_type == 'int' %}
6 6
 		<input id="{{fieldname}}" name="field_input_{{fieldname}}" type="text" value="{{value}}" />
7
+        
8
+        
7 9
 	{% else %}
8 10
 		Unsupported base type "{{field.base_type}}" </br>
9 11
 	{% endif %}

+ 1
- 1
plugins/webui/templates/listing/list_classes.html View File

@@ -10,7 +10,7 @@
10 10
     {% else %}
11 11
     {% set abst = ' - ' ~ classe.get(None)|length %}
12 12
     {% endif %}
13
-    <li> <a href="show_class?name={{ classe.__name__ }}" target="_blank">{{ classe.__name__ }} </a>{{ abst }}</li>
13
+    <li> <a href="show_class?classname={{ classe.__name__ }}" target="_blank">{{ classe.__name__ }} </a>{{ abst }}</li>
14 14
     {% endfor %}
15 15
 </ul>
16 16
 {% endblock %}

+ 4
- 5
plugins/webui/templates/listing/show_class.html View File

@@ -1,9 +1,8 @@
1 1
 {% extends "base.html" %}
2
-{% set my_classname = params['name'].pop() %}
3
-{% block title %}Lodel 2 - Class {{ my_classname }} {% endblock %}
2
+{% block title %}Lodel 2 - Class {{ classname }} {% endblock %}
4 3
 {% block content %} 
5
-<h1>Lodel 2 - Class {{ my_classname }} </h1>
6
- {% set my_class  = leapi.Object.name2class(my_classname) %}
4
+<h1>Lodel 2 - Class {{ classname }} </h1>
5
+ {% set my_class  = leapi.Object.name2class(classname) %}
7 6
  {% if my_class.child_classes()|length >0 %}
8 7
      <h2> Childs classes</h2>
9 8
      <ul>
@@ -22,7 +21,7 @@
22 21
     {% set objects = my_class.get(None) %}
23 22
     <ul>
24 23
     {% for obj in objects %}
25
-        <li><a href="show_object?classe={{ my_classname }}&id={{ obj.uid() }}" target="_blank">{{ obj.uid() }} </a></li>
24
+        <li><a href="show_object?classname={{ classname }}&lodel_id={{ obj.uid() }}" target="_blank">{{ obj.uid() }} </a></li>
26 25
     {% endfor %}
27 26
     </ul>
28 27
  {% endif %}

+ 23
- 8
plugins/webui/templates/listing/show_object.html View File

@@ -1,20 +1,35 @@
1 1
 {% extends "base.html" %}
2 2
 {% import 'components/components.html' as components %}
3
-{% set my_classname = params['classe'].pop() %}
4
-{% set my_id = params['id'].pop() %}
5
-{% set my_class = leapi.Object.name2class(my_classname) %}
6
-{% set objects = my_class.get(('%s = %s') % ('lodel_id', my_id)) %}
3
+{% set my_class = leapi.Object.name2class(classname) %}
4
+{% set objects = my_class.get(('lodel_id = %s') % (lodel_id)) %}
7 5
 {% set obj = objects.pop() %}
8
-{% block title %}Lodel 2 - Object {{ my_id }} {% endblock %}
6
+{% if my_class.is_abstract() %}
7
+{{ obj.classname}}
8
+{% set classname = obj.classname %}
9
+{% set my_class = my_class.name2class(classname) %}
10
+{% endif %}
11
+{% block title %}Lodel 2 - Object {{ lodel_id }} {% endblock %}
9 12
 {% import "components/components.html" as components %}
10 13
 {% block content %}
11
-<h1>Lodel 2 - Object {{ my_id }} of the class {{ my_classname }}</h1>
14
+<h1>Lodel 2 - Object {{ lodel_id }} of the class {{ classname }}</h1>
12 15
     
13 16
 <ul>
14 17
     <!-- To get a component HTML code, it is necessary to call : components.<macro_name>(args) -->
15
-    {% for fieldname, fieldvalue in obj.datas().items() %}
18
+    {% for fieldname, fieldvalue in obj.fields().items() %}
16 19
         {% if fieldvalue is not none %}
17
-    <li> {{ fieldname }} : {{ fieldvalue }} </li>
20
+           {% if fieldvalue.base_type == 'ref' %}
21
+                {% if obj.data(fieldname) is iterable %}
22
+                    <li>{{ fieldname }}
23
+                        <ul>
24
+                    {% for rel in obj.data(fieldname) %}
25
+                            {% set l_classe = fieldvalue.allowed_classes %}
26
+                            <li><a href="show_object?classname={{ l_classe.__name__ }}&lodel_id={{ rel|int }}" target="_blank">{{ rel|int }}</a></li>
27
+                    {% endfor %}
28
+                        </ul></li>
29
+                {% endif %}
30
+            {% else %}
31
+                <li> {{ fieldname }} : {{ obj.data(fieldname) }} </li>
32
+            {% endif %}
18 33
         {% endif %}
19 34
     {% endfor %}
20 35
 </ul>

Loading…
Cancel
Save