Преглед изворни кода

First version of the DjangoMigrationHandler. Created a LodelTestInstance for tests purpose

Some problems are still to solve (see the todo comments in EditorialModel/migrationhandler/django.py )
Yann Weber пре 9 година
родитељ
комит
74f1de0f4b

+ 147
- 0
EditorialModel/migrationhandler/django.py Прегледај датотеку

@@ -0,0 +1,147 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+import django
4
+from django.db import models
5
+from django.contrib import admin
6
+
7
+## @package EditorialModel.migrationhandler.django
8
+# @brief A migration handler for django ORM
9
+#
10
+# Create django models according to the editorial model
11
+
12
+##
13
+# @source https://code.djangoproject.com/wiki/DynamicModels
14
+#
15
+def create_model(name, fields=None, app_label='', module='', options=None, admin_opts=None, parent_class=None):
16
+    class Meta:
17
+        # Using type('Meta', ...) gives a dictproxy error during model creation
18
+        pass
19
+
20
+    if app_label:
21
+        # app_label must be set using the Meta inner class
22
+        setattr(Meta, 'app_label', app_label)
23
+
24
+    # Update Meta with any options that were provided
25
+    if options is not None:
26
+        for key, value in options.iteritems():
27
+            setattr(Meta, key, value)
28
+
29
+    # Set up a dictionary to simulate declarations within a class
30
+    attrs = {'__module__': module, 'Meta':Meta}
31
+
32
+    # Add in any fields that were provided
33
+    if fields:
34
+        attrs.update(fields)
35
+
36
+    # Create the class, which automatically triggers ModelBase processing
37
+    if parent_class is None:
38
+        parent_class = models.Model
39
+    model = type(name, (parent_class,), attrs)
40
+
41
+    # Create an Admin class if admin options were provided
42
+    if admin_opts is not None:
43
+        class Admin(admin.ModelAdmin):
44
+            pass
45
+        for key, value in admin_opts:
46
+            setattr(Admin, key, value)
47
+        admin.site.register(model, Admin)
48
+    return model
49
+
50
+
51
+
52
+class DjangoMigrationHandler(object):
53
+
54
+    app_label = 'lodel'
55
+
56
+    def __init__(self, debug=False):
57
+        self.debug = debug
58
+
59
+    def register_change(self, uid, initial_state, new_state):
60
+        pass
61
+
62
+    def register_model_state(self, state_hash):
63
+        pass
64
+
65
+    ## @brief Return the models save method
66
+    #
67
+    # The save function of our class and type models is used to set unconditionnaly the
68
+    # classtype, class_name and type_name models property
69
+    # 
70
+    # @param classname str: The classname used to call the super().save
71
+    # @param level str: Wich type of model are we doing. Possible values are 'class' and 'type'
72
+    # @param datas list : List of property => value to set in the save function
73
+    # @return The wanted save function
74
+    def get_save_fun(self, classname, level, datas):
75
+        
76
+        if level == 'class':
77
+            def save(self, *args, **kwargs):
78
+                self.classtype = datas['classtype']
79
+                self.class_name = datas['class_name']
80
+                super(classname, self).save(*args, **kwargs)
81
+        elif level == 'type':
82
+            def save(self, *args, **kwargs):
83
+                self.type_name = datas['type_name']
84
+                super(classname, self).save(*args, **kwargs)
85
+
86
+        return save
87
+
88
+    ## @brief Create django models from an EditorialModel.model object
89
+    # @param me EditorialModel.model.Model : The editorial model instance
90
+    # @return a dict with all the models
91
+    # @todo Handle fieldgroups
92
+    # @todo write and use a function to forge models name from EmClasses and EmTypes names
93
+    # @note There is a problem with the related_name for superiors fk : The related name cannot be subordinates, it has to be the subordinates em_type name
94
+    def me_to_models(self, me, app_label, module_name):
95
+        #Creating the document model
96
+        document_attrs = {
97
+            'lodel_id' : models.AutoField(primary_key=True),
98
+            'classtype': models.CharField(max_length=16, editable=False),
99
+            'class_name': models.CharField(max_length=16, editable=False),
100
+            'type_name': models.CharField(max_length=16, editable=False),
101
+            'string' : models.CharField(max_length=255),
102
+            'date_update': models.DateTimeField(auto_now=True, auto_now_add=True),
103
+            'date_create': models.DateTimeField(auto_now_add=True),
104
+            'rank' : models.IntegerField(),
105
+            'help_text': models.CharField(max_length=255),
106
+        }
107
+
108
+        #Creating the base model document
109
+        document_model = create_model('document', document_attrs, app_label, module_name)
110
+
111
+        django_models = {'doc' : document_model, 'classes':{}, 'types':{} }
112
+
113
+        classes = me.classes()
114
+
115
+        #Creating the EmClasses models with document inheritance
116
+        for emclass in classes:
117
+            emclass_fields = {
118
+                'save' : self.get_save_fun(emclass.name, 'class', { 'classtype':emclass.classtype, 'class_name':emclass.name})
119
+            }
120
+
121
+            #Addding non optionnal fields
122
+            for emfield in emclass.fields():
123
+                if not emfield.optional:
124
+                    # !!! Replace with fieldtype 2 django converter
125
+                    emclass_fields[emfield.name] = models.CharField(max_length=56, default=emfield.name)
126
+            print("Model for class %s created with fields : "%emclass.name, emclass_fields)
127
+            django_models['classes'][emclass.name] = create_model(emclass.name, emclass_fields, app_label, module_name, parent_class=django_models['doc'])
128
+            
129
+            #Creating the EmTypes models with EmClass inherithance
130
+            for emtype in emclass.types():
131
+                emtype_fields = {
132
+                    'save': self.get_save_fun(emtype.name, 'type', { 'type_name':emtype.name }),
133
+
134
+                }
135
+                #Adding selected optionnal fields
136
+                for emfield in emtype.selected_fields():
137
+                    emtype_fields[emfield.name] = models.CharField(max_length=56, default=emfield.name)
138
+                #Adding superiors foreign key
139
+                for nature, superior in emtype.superiors().items():
140
+                    emtype_fields[nature] = models.ForeignKey(superior.name, related_name=emtype.name, null=True)
141
+
142
+                print("Model for type %s created with fields : "%emtype.name, emtype_fields)
143
+                django_models['types'][emtype.name] = create_model(emtype.name, emtype_fields, app_label, module_name, parent_class=django_models['classes'][emclass.name])
144
+
145
+        return django_models
146
+
147
+

+ 1
- 0
EditorialModel/migrationhandler/dummy.py Прегледај датотеку

@@ -14,6 +14,7 @@ class DummyMigrationHandler(object):
14 14
 
15 15
     ## @brief Record a change in the EditorialModel and indicate wether or not it is possible to make it
16 16
     # @note The states ( initial_state and new_state ) contains only fields that changes
17
+    # @param context model : The EditorialModel.model object to provide the global context
17 18
     # @param uid int : The uid of the change EmComponent
18 19
     # @param initial_state dict | None : dict with field name as key and field value as value. Representing the original state. None mean creation of a new component.
19 20
     # @param new_state dict | None : dict with field name as key and field value as value. Representing the new state. None mean component deletion

+ 0
- 0
LodelTestInstance/__init__.py Прегледај датотеку


+ 3
- 0
LodelTestInstance/admin.py Прегледај датотеку

@@ -0,0 +1,3 @@
1
+from django.contrib import admin
2
+
3
+# Register your models here.

+ 15
- 0
LodelTestInstance/models.py Прегледај датотеку

@@ -0,0 +1,15 @@
1
+from django.db import models
2
+
3
+from EditorialModel.migrationhandler.django import DjangoMigrationHandler
4
+from EditorialModel.migrationhandler.dummy import DummyMigrationHandler
5
+from EditorialModel.model import Model
6
+from EditorialModel.backend.json_backend import EmBackendJson
7
+
8
+
9
+me = Model(EmBackendJson('EditorialModel/test/me.json'), migration_handler = DummyMigrationHandler(True))
10
+
11
+dmh = DjangoMigrationHandler()
12
+
13
+models = dmh.me_to_models(me,'LodelTestInstance', 'LodelTestInstance.models')
14
+
15
+

+ 3
- 0
LodelTestInstance/tests.py Прегледај датотеку

@@ -0,0 +1,3 @@
1
+from django.test import TestCase
2
+
3
+# Create your tests here.

+ 3
- 0
LodelTestInstance/views.py Прегледај датотеку

@@ -0,0 +1,3 @@
1
+from django.shortcuts import render
2
+
3
+# Create your views here.

+ 1
- 0
requirements.txt Прегледај датотеку

@@ -1 +1,2 @@
1 1
 Django==1.7.8
2
+mysqlclient

Loading…
Откажи
Сачувај