|
@@ -12,7 +12,6 @@ from EditorialModel.migrationhandler.dummy import DummyMigrationHandler
|
12
|
12
|
from EditorialModel.exceptions import *
|
13
|
13
|
|
14
|
14
|
|
15
|
|
-
|
16
|
15
|
## @brief Create a django model
|
17
|
16
|
# @param name str : The django model name
|
18
|
17
|
# @param fields dict : A dict that contains fields name and type ( str => DjangoField )
|
|
@@ -39,7 +38,7 @@ def create_model(name, fields=None, app_label='', module='', options=None, admin
|
39
|
38
|
setattr(Meta, key, value)
|
40
|
39
|
|
41
|
40
|
# Set up a dictionary to simulate declarations within a class
|
42
|
|
- attrs = {'__module__': module, 'Meta':Meta}
|
|
41
|
+ attrs = {'__module__': module, 'Meta': Meta}
|
43
|
42
|
|
44
|
43
|
# Add in any fields that were provided
|
45
|
44
|
if fields:
|
|
@@ -91,7 +90,7 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
91
|
90
|
#
|
92
|
91
|
# @warning broken because of : https://code.djangoproject.com/ticket/24735 you have to patch django/core/management/commands/makemigrations.py w/django/core/management/commands/makemigrations.py
|
93
|
92
|
def register_change(self, em, uid, initial_state, new_state):
|
94
|
|
-
|
|
93
|
+
|
95
|
94
|
#Starting django
|
96
|
95
|
os.environ['LODEL_MIGRATION_HANDLER_TESTS'] = 'YES'
|
97
|
96
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Lodel.settings")
|
|
@@ -110,7 +109,7 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
110
|
109
|
django_cmd('makemigrations', self.app_name, dry_run=True, interactive=False)
|
111
|
110
|
except django.core.management.base.CommandError as e:
|
112
|
111
|
raise MigrationHandlerChangeError(str(e))
|
113
|
|
-
|
|
112
|
+
|
114
|
113
|
return True
|
115
|
114
|
|
116
|
115
|
## @brief Print a debug message representing a migration
|
|
@@ -141,7 +140,7 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
141
|
140
|
print(str_chg)
|
142
|
141
|
print("##############\n")
|
143
|
142
|
pass
|
144
|
|
-
|
|
143
|
+
|
145
|
144
|
## @brief Register a new model state and update the data representation given the new state
|
146
|
145
|
# @param em model : The EditorialModel to migrate
|
147
|
146
|
# @param state_hash str : Note usefull (for the moment ?)
|
|
@@ -171,7 +170,7 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
171
|
170
|
#Calling migrate to update the database schema
|
172
|
171
|
django_cmd('migrate', self.app_name, interactive=False, noinput=True)
|
173
|
172
|
except django.core.management.base.CommandError as e:
|
174
|
|
- raise MigrationHandlerChangeError("Unable to migrate to new model state : %s"%e)
|
|
173
|
+ raise MigrationHandlerChangeError("Unable to migrate to new model state : %s" % e)
|
175
|
174
|
|
176
|
175
|
pass
|
177
|
176
|
|
|
@@ -179,13 +178,13 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
179
|
178
|
#
|
180
|
179
|
# The save function of our class and type models is used to set unconditionnaly the
|
181
|
180
|
# classtype, class_name and type_name models property
|
182
|
|
- #
|
|
181
|
+ #
|
183
|
182
|
# @param classname str: The classname used to call the super().save
|
184
|
183
|
# @param level str: Wich type of model are we doing. Possible values are 'class' and 'type'
|
185
|
184
|
# @param datas list : List of property => value to set in the save function
|
186
|
185
|
# @return The wanted save function
|
187
|
186
|
def get_save_fun(self, classname, level, datas):
|
188
|
|
-
|
|
187
|
+
|
189
|
188
|
if level == 'class':
|
190
|
189
|
def save(self, *args, **kwargs):
|
191
|
190
|
self.classtype = datas['classtype']
|
|
@@ -197,7 +196,7 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
197
|
196
|
super(classname, self).save(*args, **kwargs)
|
198
|
197
|
|
199
|
198
|
return save
|
200
|
|
-
|
|
199
|
+
|
201
|
200
|
## @brief Create django models from an EditorialModel.model object
|
202
|
201
|
# @param edMod EditorialModel.model.Model : The editorial model instance
|
203
|
202
|
# @return a dict with all the models
|
|
@@ -205,8 +204,8 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
205
|
204
|
# @todo write and use a function to forge models name from EmClasses and EmTypes names
|
206
|
205
|
# @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
|
207
|
206
|
def em_to_models(self, edMod):
|
208
|
|
-
|
209
|
|
- module_name = self.app_name+'.models'
|
|
207
|
+
|
|
208
|
+ module_name = self.app_name + '.models'
|
210
|
209
|
|
211
|
210
|
#Purging django models cache
|
212
|
211
|
if self.app_name in django_cache.all_models:
|
|
@@ -214,32 +213,31 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
214
|
213
|
del(django_cache.all_models[self.app_name][modname])
|
215
|
214
|
#del(django_cache.all_models[self.app_name])
|
216
|
215
|
|
217
|
|
-
|
218
|
216
|
app_name = self.app_name
|
219
|
217
|
#Creating the document model
|
220
|
218
|
document_attrs = {
|
221
|
|
- 'lodel_id' : models.AutoField(primary_key=True),
|
|
219
|
+ 'lodel_id': models.AutoField(primary_key=True),
|
222
|
220
|
'classtype': models.CharField(max_length=16, editable=False),
|
223
|
221
|
'class_name': models.CharField(max_length=16, editable=False),
|
224
|
222
|
'type_name': models.CharField(max_length=16, editable=False),
|
225
|
|
- 'string' : models.CharField(max_length=255),
|
|
223
|
+ 'string': models.CharField(max_length=255),
|
226
|
224
|
'date_update': models.DateTimeField(auto_now=True, auto_now_add=True),
|
227
|
225
|
'date_create': models.DateTimeField(auto_now_add=True),
|
228
|
|
- 'rank' : models.IntegerField(),
|
|
226
|
+ 'rank': models.IntegerField(),
|
229
|
227
|
'help_text': models.CharField(max_length=255),
|
230
|
228
|
}
|
231
|
229
|
|
232
|
230
|
#Creating the base model document
|
233
|
231
|
document_model = create_model('document', document_attrs, self.app_name, module_name)
|
234
|
232
|
|
235
|
|
- django_models = {'doc' : document_model, 'classes':{}, 'types':{} }
|
|
233
|
+ django_models = {'doc': document_model, 'classes': {}, 'types': {}}
|
236
|
234
|
|
237
|
235
|
classes = edMod.classes()
|
238
|
236
|
|
239
|
237
|
#Creating the EmClasses models with document inheritance
|
240
|
238
|
for emclass in classes:
|
241
|
239
|
emclass_fields = {
|
242
|
|
- 'save' : self.get_save_fun(emclass.uniq_name, 'class', { 'classtype':emclass.classtype, 'class_name':emclass.uniq_name}),
|
|
240
|
+ 'save': self.get_save_fun(emclass.uniq_name, 'class', {'classtype': emclass.classtype, 'class_name': emclass.uniq_name}),
|
243
|
241
|
}
|
244
|
242
|
|
245
|
243
|
#Addding non optionnal fields
|
|
@@ -250,13 +248,13 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
250
|
248
|
emclass_fields[emfield.uniq_name] = self.field_to_django(emfield, emclass)
|
251
|
249
|
#print("Model for class %s created with fields : "%emclass.uniq_name, emclass_fields)
|
252
|
250
|
if self.debug:
|
253
|
|
- print("Model for class %s created"%emclass.uniq_name)
|
|
251
|
+ print("Model for class %s created" % emclass.uniq_name)
|
254
|
252
|
django_models['classes'][emclass.uniq_name] = create_model(emclass.uniq_name, emclass_fields, self.app_name, module_name, parent_class=django_models['doc'])
|
255
|
|
-
|
|
253
|
+
|
256
|
254
|
#Creating the EmTypes models with EmClass inherithance
|
257
|
255
|
for emtype in emclass.types():
|
258
|
256
|
emtype_fields = {
|
259
|
|
- 'save': self.get_save_fun(emtype.uniq_name, 'type', { 'type_name':emtype.uniq_name }),
|
|
257
|
+ 'save': self.get_save_fun(emtype.uniq_name, 'type', {'type_name': emtype.uniq_name}),
|
260
|
258
|
}
|
261
|
259
|
#Adding selected optionnal fields
|
262
|
260
|
for emfield in emtype.selected_fields():
|
|
@@ -268,7 +266,7 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
268
|
266
|
emtype_fields[nature] = models.ForeignKey(superior.uniq_name, related_name=emtype.uniq_name, null=True)
|
269
|
267
|
|
270
|
268
|
if self.debug:
|
271
|
|
- print("Model for type %s created"%emtype.uniq_name)
|
|
269
|
+ print("Model for type %s created" % emtype.uniq_name)
|
272
|
270
|
django_models['types'][emtype.uniq_name] = create_model(emtype.uniq_name, emtype_fields, self.app_name, module_name, parent_class=django_models['classes'][emclass.uniq_name])
|
273
|
271
|
|
274
|
272
|
pass
|
|
@@ -285,32 +283,32 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
285
|
283
|
args['null'] = f.nullable
|
286
|
284
|
if not (f.default is None):
|
287
|
285
|
args['default'] = f.default
|
288
|
|
- v_fun = f.validation_function(raise_e = ValidationError)
|
|
286
|
+ v_fun = f.validation_function(raise_e=ValidationError)
|
289
|
287
|
if v_fun:
|
290
|
288
|
args['validators'] = [v_fun]
|
291
|
289
|
if f.uniq:
|
292
|
290
|
args['unique'] = True
|
293
|
|
-
|
|
291
|
+
|
294
|
292
|
# Field instanciation
|
295
|
|
- if f.ftype == 'char': #varchar field
|
|
293
|
+ if f.ftype == 'char': # varchar field
|
296
|
294
|
args['max_length'] = f.max_length
|
297
|
295
|
return models.CharField(**args)
|
298
|
|
- elif f.ftype == 'int': #integer field
|
|
296
|
+ elif f.ftype == 'int': # integer field
|
299
|
297
|
return models.IntegerField(**args)
|
300
|
|
- elif f.ftype == 'text': #text field
|
|
298
|
+ elif f.ftype == 'text': # text field
|
301
|
299
|
return models.TextField(**args)
|
302
|
|
- elif f.ftype == 'datetime': #Datetime field
|
|
300
|
+ elif f.ftype == 'datetime': # Datetime field
|
303
|
301
|
args['auto_now'] = f.now_on_update
|
304
|
302
|
args['auto_now_add'] = f.now_on_create
|
305
|
303
|
return models.DateTimeField(**args)
|
306
|
|
- elif f.ftype == 'bool': #Boolean field
|
|
304
|
+ elif f.ftype == 'bool': # Boolean field
|
307
|
305
|
if args['null']:
|
308
|
306
|
return models.NullBooleanField(**args)
|
309
|
307
|
del(args['null'])
|
310
|
308
|
return models.BooleanField(**args)
|
311
|
|
- elif f.ftype == 'rel2type': #Relation to type
|
|
309
|
+ elif f.ftype == 'rel2type': # Relation to type
|
312
|
310
|
|
313
|
|
- if assoc_comp == None:
|
|
311
|
+ if assoc_comp is None:
|
314
|
312
|
raise RuntimeError("Rel2type field in a rel2type table is not allowed")
|
315
|
313
|
#create first a throught model if there is data field associated with the relation
|
316
|
314
|
kwargs = dict()
|
|
@@ -318,7 +316,7 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
318
|
316
|
relf_l = f.get_related_fields()
|
319
|
317
|
if len(relf_l) > 0:
|
320
|
318
|
through_fields = {}
|
321
|
|
-
|
|
319
|
+
|
322
|
320
|
#The two FK of the through model
|
323
|
321
|
through_fields[assoc_comp.name] = models.ForeignKey(assoc_comp.uniq_name)
|
324
|
322
|
rtype = f.get_related_type()
|
|
@@ -328,16 +326,12 @@ class DjangoMigrationHandler(DummyMigrationHandler):
|
328
|
326
|
through_fields[relf.name] = self.field_to_django(relf, None)
|
329
|
327
|
|
330
|
328
|
#through_model_name = f.uniq_name+assoc_comp.uniq_name+'to'+rtype.uniq_name
|
331
|
|
- through_model_name = f.name+assoc_comp.name+'to'+rtype.name
|
332
|
|
- module_name = self.app_name+'.models'
|
|
329
|
+ through_model_name = f.name + assoc_comp.name + 'to' + rtype.name
|
|
330
|
+ module_name = self.app_name + '.models'
|
333
|
331
|
#model created
|
334
|
332
|
through_model = create_model(through_model_name, through_fields, self.app_name, module_name)
|
335
|
333
|
kwargs['through'] = through_model_name
|
336
|
|
-
|
337
|
|
- return models.ManyToManyField(f.get_related_type().uniq_name, **kwargs)
|
338
|
|
- else: #Unknow data type
|
339
|
|
- raise NotImplemented("The conversion to django fields is not yet implemented for %s field type"%f.ftype)
|
340
|
|
-
|
341
|
|
-
|
342
|
|
-
|
343
|
334
|
|
|
335
|
+ return models.ManyToManyField(f.get_related_type().uniq_name, **kwargs)
|
|
336
|
+ else: # Unknow data type
|
|
337
|
+ raise NotImplemented("The conversion to django fields is not yet implemented for %s field type" % f.ftype)
|