|
a/OSSEval/analysis/models.py |
|
b/OSSEval/analysis/models.py |
|
|
1 |
import importlib
|
1 |
from django.db import models
|
2 |
from django.db import models
|
2 |
from datetime import datetime
|
3 |
from datetime import datetime
|
3 |
from random import randrange
|
4 |
from random import randrange
|
4 |
from pygal import Radar, Bar
|
5 |
from pygal import Radar, Bar
|
5 |
from pygal.style import NeonStyle, DarkSolarizedStyle, LightSolarizedStyle, LightStyle, CleanStyle, RedBlueStyle, DarkColorizedStyle, LightColorizedStyle, TurquoiseStyle, LightGreenStyle, DarkGreenStyle, DarkGreenBlueStyle, BlueStyle
|
6 |
from pygal.style import NeonStyle, DarkSolarizedStyle, LightSolarizedStyle, LightStyle, CleanStyle, RedBlueStyle, DarkColorizedStyle, LightColorizedStyle, TurquoiseStyle, LightGreenStyle, DarkGreenStyle, DarkGreenBlueStyle, BlueStyle
|
|
... |
|
... |
39 |
return '<Methodology Id="' + str(self.id) + '" Name="' + self.name + '" Active="' + str(self.active) + '">' + str_xml + "</Methodology>"
|
40 |
return '<Methodology Id="' + str(self.id) + '" Name="' + self.name + '" Active="' + str(self.active) + '">' + str_xml + "</Methodology>"
|
40 |
|
41 |
|
41 |
class HasPages(models.Model):
|
42 |
class HasPages(models.Model):
|
42 |
bar_chart = models.TextField(blank=True)
|
43 |
bar_chart = models.TextField(blank=True)
|
43 |
radar_chart = models.TextField(blank=True)
|
44 |
radar_chart = models.TextField(blank=True)
|
44 |
def create_graphs(self, instances):
|
45 |
def create_graphs(self, instances, include_max = True):
|
45 |
# I draw the graphs for the report
|
46 |
# I draw the graphs for the report
|
46 |
#styles = [NeonStyle, DarkSolarizedStyle, LightSolarizedStyle, LightStyle, CleanStyle, RedBlueStyle, DarkColorizedStyle, LightColorizedStyle, TurquoiseStyle, LightGreenStyle, DarkGreenStyle, DarkGreenBlueStyle, BlueStyle]
|
47 |
#styles = [NeonStyle, DarkSolarizedStyle, LightSolarizedStyle, LightStyle, CleanStyle, RedBlueStyle, DarkColorizedStyle, LightColorizedStyle, TurquoiseStyle, LightGreenStyle, DarkGreenStyle, DarkGreenBlueStyle, BlueStyle]
|
47 |
#style=styles[randrange(len(styles))]
|
48 |
#style=styles[randrange(len(styles))]
|
48 |
style=LightColorizedStyle
|
49 |
style=LightColorizedStyle
|
49 |
bar_chart = Bar(width=300, height=400, explicit_size=True, rounded_bars=5, disable_xml_declaration=True, style=style)
|
50 |
bar_chart = Bar(width=300, height=400, explicit_size=True, rounded_bars=5, disable_xml_declaration=True, style=style)
|
|
... |
|
... |
54 |
radar_chart.title = 'Summary graph'
|
55 |
radar_chart.title = 'Summary graph'
|
55 |
radar_chart.x_labels = []
|
56 |
radar_chart.x_labels = []
|
56 |
instance_scores = {}
|
57 |
instance_scores = {}
|
57 |
for instance in instances:
|
58 |
for instance in instances:
|
58 |
instance_scores[instance.id] = []
|
59 |
instance_scores[instance.id] = []
|
|
|
60 |
if include_max:
|
|
|
61 |
# I use 0 as an id for the max score
|
|
|
62 |
instance_scores[0] = []
|
59 |
for page in self.page_set.all():
|
63 |
for page in self.page_set.all():
|
60 |
radar_chart.x_labels.append(page.name)
|
64 |
radar_chart.x_labels.append(page.name)
|
61 |
for instance in instances:
|
65 |
for instance in instances:
|
62 |
try:
|
66 |
try:
|
63 |
ps = PageScore.objects.get(page=page, instance=instance)
|
67 |
ps = PageScore.objects.get(page=page, instance=instance)
|
64 |
instance_scores[instance.id].append(ps.score)
|
68 |
instance_scores[instance.id].append(ps.score)
|
65 |
except:
|
69 |
except:
|
66 |
instance_scores[instance.id].append(0)
|
70 |
instance_scores[instance.id].append(0)
|
|
|
71 |
if include_max:
|
|
|
72 |
instance_scores[0].append(5)
|
|
|
73 |
print str(page.id) + " - " + str(page.max_score)
|
67 |
for instance in instances:
|
74 |
for instance in instances:
|
68 |
radar_chart.add(instance.name, instance_scores[instance.id])
|
75 |
radar_chart.add(instance.name, instance_scores[instance.id])
|
69 |
bar_chart.add(instance.name, sum(instance_scores[instance.id]))
|
76 |
bar_chart.add(instance.name, sum(instance_scores[instance.id]))
|
|
|
77 |
if include_max:
|
|
|
78 |
radar_chart.add("MAX", instance_scores[0])
|
|
|
79 |
bar_chart.add("MAX", sum(instance_scores[0]))
|
70 |
self.radar_chart = radar_chart.render()
|
80 |
self.radar_chart = radar_chart.render()
|
71 |
self.bar_chart = bar_chart.render()
|
81 |
self.bar_chart = bar_chart.render()
|
72 |
self.save()
|
82 |
self.save()
|
73 |
class Meta:
|
83 |
class Meta:
|
74 |
abstract = True
|
84 |
abstract = True
|
|
... |
|
... |
126 |
class Page(HasPages):
|
136 |
class Page(HasPages):
|
127 |
name = models.CharField(max_length=200)
|
137 |
name = models.CharField(max_length=200)
|
128 |
order = models.IntegerField(null=False,blank=False)
|
138 |
order = models.IntegerField(null=False,blank=False)
|
129 |
parent = models.ForeignKey('self',null=True,blank=True)
|
139 |
parent = models.ForeignKey('self',null=True,blank=True)
|
130 |
methodology_version = models.ForeignKey(MethodologyVersion,null=True,blank=True)
|
140 |
methodology_version = models.ForeignKey(MethodologyVersion,null=True,blank=True)
|
|
|
141 |
max_score = 0
|
131 |
def questions(self):
|
142 |
def questions(self):
|
132 |
q = list(self.question_set.all())
|
143 |
q = list(self.question_set.all())
|
133 |
for p in self.page_set.all():
|
144 |
for p in self.page_set.all():
|
134 |
q += p.questions()
|
145 |
q += p.questions()
|
135 |
return q
|
146 |
return q
|
|
... |
|
... |
178 |
str_xml += question.to_xml()
|
189 |
str_xml += question.to_xml()
|
179 |
str_xml += "</Questions>"
|
190 |
str_xml += "</Questions>"
|
180 |
return '<Page Id="' + str(self.id) + '" Name="' + self.name + '" Order="' + str(self.order) + '">' + str_xml + "</Page>"
|
191 |
return '<Page Id="' + str(self.id) + '" Name="' + self.name + '" Order="' + str(self.order) + '">' + str_xml + "</Page>"
|
181 |
|
192 |
|
182 |
def calculate_scores(self, instance, weight_scenario, instances):
|
193 |
def calculate_scores(self, instance, weight_scenario, instances):
|
|
|
194 |
self.max_score = 5
|
183 |
# Let's reset the score to 0
|
195 |
# Let's reset the score to 0
|
184 |
try:
|
196 |
try:
|
185 |
ps = PageScore.objects.get(page=self, instance=instance)
|
197 |
ps = PageScore.objects.get(page=self, instance=instance)
|
186 |
except:
|
198 |
except:
|
187 |
ps = PageScore(page=self, instance=instance, score=0)
|
199 |
ps = PageScore(page=self, instance=instance, score=0)
|
|
... |
|
... |
319 |
return '<Choice Id="' + str(self.id) + '" Text="' + self.text + '" Order="' + str(self.order) + '">' + str_xml + '</Choice>'
|
331 |
return '<Choice Id="' + str(self.id) + '" Text="' + self.text + '" Order="' + str(self.order) + '">' + str_xml + '</Choice>'
|
320 |
|
332 |
|
321 |
class Meta:
|
333 |
class Meta:
|
322 |
ordering = ['order']
|
334 |
ordering = ['order']
|
323 |
|
335 |
|
|
|
336 |
class Weight():
|
|
|
337 |
'''
|
|
|
338 |
used by WeightScenario so I need to define it first
|
|
|
339 |
'''
|
|
|
340 |
pass
|
|
|
341 |
|
324 |
class WeightScenario(models.Model):
|
342 |
class WeightScenario(models.Model):
|
325 |
name = models.CharField(max_length=200)
|
343 |
name = models.CharField(max_length=200)
|
326 |
methodology_version = models.ForeignKey(MethodologyVersion)
|
344 |
methodology_version = models.ForeignKey(MethodologyVersion)
|
327 |
active = models.BooleanField(blank=False)
|
345 |
active = models.BooleanField(blank=False)
|
328 |
|
346 |
|
|
... |
|
... |
333 |
weight = 1
|
351 |
weight = 1
|
334 |
for w in self.weight_set.all():
|
352 |
for w in self.weight_set.all():
|
335 |
if w.question.id == question_id:
|
353 |
if w.question.id == question_id:
|
336 |
weight = w.weight
|
354 |
weight = w.weight
|
337 |
return weight
|
355 |
return weight
|
|
|
356 |
|
338 |
def from_xml(self, xmldoc, methodology_version, insert = True):
|
357 |
def from_xml(self, xmldoc, methodology_version, insert = True):
|
339 |
if not insert:
|
358 |
if not insert:
|
340 |
self.id = xmlMinidom.getNaturalAttribute(xmldoc, 'Id')
|
359 |
self.id = xmlMinidom.getNaturalAttribute(xmldoc, 'Id')
|
341 |
self.methodology_version = methodology_version
|
360 |
self.methodology_version = methodology_version
|
342 |
self.name = xmlMinidom.getStringAttribute(xmldoc, 'Name')
|
361 |
self.name = xmlMinidom.getStringAttribute(xmldoc, 'Name')
|
|
... |
|
... |
367 |
if not insert:
|
386 |
if not insert:
|
368 |
self.id = xmlMinidom.getNaturalAttribute(xmldoc, 'Id')
|
387 |
self.id = xmlMinidom.getNaturalAttribute(xmldoc, 'Id')
|
369 |
self.scenario = scenario
|
388 |
self.scenario = scenario
|
370 |
self.weight = xmlMinidom.getStringAttribute(xmldoc, 'weight')
|
389 |
self.weight = xmlMinidom.getStringAttribute(xmldoc, 'weight')
|
371 |
self.question = Question.objects.get(pk=xmlMinidom.getNaturalAttribute(xmldoc, 'question_id'))
|
390 |
self.question = Question.objects.get(pk=xmlMinidom.getNaturalAttribute(xmldoc, 'question_id'))
|
|
|
391 |
# If I am inserting I must check that there's no other Weight for the same
|
|
|
392 |
# couple ('question', 'scenario') as I have a unique_together constraint
|
|
|
393 |
if not self.id:
|
|
|
394 |
# I look for a Weight for the same question and scenario
|
|
|
395 |
try:
|
|
|
396 |
w = Weight.objects.get(scenario_id=self.scenario.id, question_id=self.question.id)
|
|
|
397 |
w.delete()
|
|
|
398 |
except:
|
|
|
399 |
# I didn't find one; nothing to do
|
|
|
400 |
pass
|
372 |
self.save()
|
401 |
self.save()
|
373 |
|
402 |
|
374 |
def to_xml(self):
|
403 |
def to_xml(self):
|
375 |
return '<Weight Id="' + str(self.id) + '" question_id="' + str(self.question.id) + '" weight="' + str(self.weight) + '"/>'
|
404 |
return '<Weight Id="' + str(self.id) + '" question_id="' + str(self.question.id) + '" weight="' + str(self.weight) + '"/>'
|
376 |
|
405 |
|
|
|
406 |
class Meta:
|
|
|
407 |
unique_together = ('question', 'scenario')
|
|
|
408 |
|
377 |
class Analysis(models.Model):
|
409 |
class Analysis(models.Model):
|
378 |
name = models.CharField(max_length=200)
|
410 |
name = models.CharField(max_length=200)
|
379 |
description = models.CharField(max_length=2000)
|
411 |
description = models.CharField(max_length=2000)
|
380 |
comment = models.TextField(null=True,blank=True)
|
412 |
comment = models.TextField(null=True,blank=True)
|
381 |
created = models.DateField(default=datetime.now, blank=True)
|
413 |
created = models.DateField(default=datetime.now, blank=True)
|
|
... |
|
... |
386 |
protected = models.BooleanField(default=False)
|
418 |
protected = models.BooleanField(default=False)
|
387 |
|
419 |
|
388 |
def __str__(self):
|
420 |
def __str__(self):
|
389 |
return self.name
|
421 |
return self.name
|
390 |
|
422 |
|
391 |
def calculate_scores(self):
|
423 |
def calculate_scores(self, weight_scenario_id):
|
392 |
'''
|
424 |
'''
|
393 |
Calculates scores for each couple (instance, page) and (instance, question)
|
425 |
Calculates scores for each couple (instance, page) and (instance, question)
|
394 |
Stores them on the db
|
426 |
Stores them on the db
|
395 |
'''
|
427 |
'''
|
396 |
#let's get the weight from the scenario if any; the default is 1
|
428 |
#let's get the weight from the scenario if any; the default is 1
|
397 |
try:
|
429 |
try:
|
398 |
weight_scenarios = self.methodology_version.weightscenario_set.filter(active=True)
|
|
|
399 |
if len(weight_scenarios) == 1:
|
430 |
if weight_scenario_id > 0:
|
400 |
weight_scenario = weight_scenarios[0]
|
431 |
weight_scenario = WeightScenario.objects.get(pk=weight_scenario_id)
|
401 |
else:
|
432 |
else:
|
402 |
raise Exception("There should be exactly one WeightScenario for MethodologyVersion " + str(self.methodology_version.id))
|
433 |
weight_scenario = self.weight_scenario
|
403 |
except:
|
434 |
except:
|
404 |
# an empty one will set all weights to 1
|
435 |
# an empty one will set all weights to 1
|
405 |
weight_scenario = WeightScenario()
|
436 |
weight_scenario = WeightScenario()
|
406 |
#loop through the pages to reset scores to 0; when I calculate a question
|
437 |
#loop through the pages to reset scores to 0; when I calculate a question
|
407 |
#then I add its score to the corresponding page
|
438 |
#then I add its score to the corresponding page
|
408 |
#loop on top level pages and recursive calculation on child pages
|
439 |
#loop on top level pages and recursive calculation on child pages
|
409 |
for page in self.methodology_version.page_set.all():
|
440 |
for page in self.methodology_version.page_set.all():
|
410 |
for instance in self.instance_set.all():
|
441 |
for instance in self.instance_set.all():
|
411 |
page.calculate_scores(instance, weight_scenario, self.instance_set.all())
|
442 |
page.calculate_scores(instance, weight_scenario, self.instance_set.all())
|
412 |
self.methodology_version.create_graphs(self.instance_set.all())
|
443 |
self.methodology_version.create_graphs(self.instance_set.all())
|
|
|
444 |
return weight_scenario
|
413 |
|
445 |
|
414 |
# @staticmethod
|
446 |
# @staticmethod
|
415 |
# def create_graphs(object, pages, instances):
|
447 |
# def create_graphs(object, pages, instances):
|
416 |
'''
|
448 |
'''
|
417 |
a static method because I need to create the same
|
449 |
a static method because I need to create the same
|
|
... |
|
... |
420 |
def from_xml(self, xmldoc, insert = True):
|
452 |
def from_xml(self, xmldoc, insert = True):
|
421 |
'''
|
453 |
'''
|
422 |
All but the MethodologyVersion so that we can independently import from xml
|
454 |
All but the MethodologyVersion so that we can independently import from xml
|
423 |
MethodologyVersion and Analysis
|
455 |
MethodologyVersion and Analysis
|
424 |
'''
|
456 |
'''
|
425 |
pass
|
457 |
if not insert:
|
|
|
458 |
self.id = xmlMinidom.getNaturalAttribute(xmldoc, 'Id')
|
|
|
459 |
self.name = xmlMinidom.getStringAttribute(xmldoc, 'Name')
|
|
|
460 |
self.comment = xmlMinidom.getStringAttribute(xmldoc, 'Comment')
|
|
|
461 |
self.created = xmlMinidom.getStringAttribute(xmldoc, 'Created')
|
|
|
462 |
self.methodology_version = MethodologyVersion.objects.get(pk=xmlMinidom.getNaturalAttribute(xmldoc, 'MethodologyVersionId'))
|
|
|
463 |
self.user_login = xmlMinidom.getStringAttribute(xmldoc, 'UserLogin')
|
|
|
464 |
self.visible = xmlMinidom.getStringAttribute(xmldoc, 'Visible')
|
|
|
465 |
self.protected = xmlMinidom.getStringAttribute(xmldoc, 'Protected')
|
|
|
466 |
#self.weight_scenario
|
|
|
467 |
xml_weight_scenario = xmldoc.getElementsByTagName('WeightScenario')[0]
|
|
|
468 |
ws = WeightScenario()
|
|
|
469 |
ws.from_xml(xml_weight_scenario, self.methodology_version, insert)
|
|
|
470 |
self.weight_scenario = ws
|
|
|
471 |
self.save()
|
|
|
472 |
#Instances
|
|
|
473 |
xml_instances = xmldoc.getElementsByTagName('Instance')
|
|
|
474 |
for xml_instance in xml_instances:
|
|
|
475 |
i = Instance()
|
|
|
476 |
i.from_xml(xml_instance, self, insert)
|
426 |
|
477 |
|
427 |
def to_xml(self):
|
478 |
def to_xml(self):
|
428 |
str_xml = "<Description>" + self.description + "</Description>"
|
479 |
str_xml = "<Description>" + self.description + "</Description>"
|
429 |
str_xml += "<Comment>" + self.comment + "</Comment>"
|
480 |
str_xml += "<Comment>" + self.comment + "</Comment>"
|
430 |
str_xml += self.weight_scenario.to_xml()
|
481 |
str_xml += self.weight_scenario.to_xml()
|
431 |
str_xml += "<Instances>"
|
482 |
str_xml += "<Instances>"
|
432 |
for instance in self.instance_set.all():
|
483 |
for instance in self.instance_set.all():
|
433 |
str_xml += instance.to_xml()
|
484 |
str_xml += instance.to_xml()
|
434 |
str_xml += "</Instances>"
|
485 |
str_xml += "</Instances>"
|
435 |
|
486 |
|
436 |
return '<Analysis Id="' + str(self.id) + '" Name="' + self.name + '" Created="' + str(self.created) + '" UserLogin="' + self.user_login + '">' + str_xml + "</Analysis>"
|
487 |
return '<Analysis Id="' + str(self.id) + '" MethodologyVersionId="' + str(self.methodology_version.id) + '" Name="' + self.name + '" Created="' + str(self.created) + '" Visible="' + str(self.visible) + '" Protected="' + str(self.protected) + '" UserLogin="' + self.user_login + '">' + str_xml + "</Analysis>"
|
437 |
|
488 |
|
438 |
class Instance(models.Model):
|
489 |
class Instance(models.Model):
|
439 |
"""
|
490 |
"""
|
440 |
It represents one of the entities we evaluate in the assessment
|
491 |
It represents one of the entities we evaluate in the assessment
|
441 |
"""
|
492 |
"""
|
442 |
name = models.CharField(max_length=200)
|
493 |
name = models.CharField(max_length=200)
|
|
|
494 |
# name_for_search is not used yet; it is intended to provide a name to be used to search the web
|
443 |
name_for_search = models.CharField(max_length=200, default="")
|
495 |
name_for_search = models.CharField(max_length=200, default="")
|
444 |
analysis = models.ForeignKey(Analysis)
|
496 |
analysis = models.ForeignKey(Analysis)
|
445 |
|
497 |
|
446 |
def __str__(self):
|
498 |
def __str__(self):
|
447 |
return self.name + " - " + self.name_for_search
|
499 |
return self.name + " - " + self.name_for_search
|
448 |
|
500 |
|
449 |
def from_xml(self, xmldoc, insert = True):
|
501 |
def from_xml(self, xmldoc, analysis, insert = True):
|
450 |
pass
|
502 |
if not insert:
|
|
|
503 |
self.id = xmlMinidom.getNaturalAttribute(xmldoc, 'Id')
|
|
|
504 |
self.name = xmlMinidom.getStringAttribute(xmldoc, 'Name')
|
|
|
505 |
#ActualInstance
|
|
|
506 |
self.analysis = analysis
|
|
|
507 |
xml_actual_instance = xmldoc.getElementsByTagName(self.analysis.methodology_version.methodology.entity.actual_entity_class)[0]
|
|
|
508 |
module = importlib.import_module(self.analysis.methodology_version.methodology.entity.actual_entity_app + ".models")
|
|
|
509 |
actual_entity_class = getattr(module, self.analysis.methodology_version.methodology.entity.actual_entity_class)
|
|
|
510 |
self.actual_instance = actual_entity_class()
|
|
|
511 |
self.actual_instance.from_xml(xml_actual_instance, self, insert)
|
|
|
512 |
self.save()
|
|
|
513 |
#Answers
|
|
|
514 |
xml_answers = xmldoc.getElementsByTagName('Answer')
|
|
|
515 |
for xml_answer in xml_answers:
|
|
|
516 |
a = Answer()
|
|
|
517 |
a.from_xml(xml_answer, self, insert)
|
451 |
|
518 |
|
452 |
def to_xml(self):
|
519 |
def to_xml(self):
|
453 |
str_xml = "<Answers>"
|
520 |
str_xml = "<Answers>"
|
454 |
for answer in self.answer_set.all():
|
521 |
for answer in self.answer_set.all():
|
455 |
str_xml += answer.to_xml()
|
522 |
str_xml += answer.to_xml()
|
456 |
str_xml += "</Answers>"
|
523 |
str_xml += "</Answers>"
|
457 |
|
524 |
str_xml += self.actual_instance.to_xml()
|
458 |
return '<Instance Id="' + str(self.id) + '" Name="' + self.name + '" NameForSearch="' + self.name_for_search + '">' + str_xml + "</Instance>"
|
525 |
return '<Instance Id="' + str(self.id) + '" Name="' + self.name + '">' + str_xml + "</Instance>"
|
459 |
|
526 |
|
460 |
class PageScore(models.Model):
|
527 |
class PageScore(models.Model):
|
461 |
page = models.ForeignKey(Page)
|
528 |
page = models.ForeignKey(Page)
|
462 |
instance = models.ForeignKey(Instance)
|
529 |
instance = models.ForeignKey(Instance)
|
463 |
score = models.FloatField()
|
530 |
score = models.FloatField()
|
|
... |
|
... |
475 |
question = models.ForeignKey(Question)
|
542 |
question = models.ForeignKey(Question)
|
476 |
value_integer = models.IntegerField()
|
543 |
value_integer = models.IntegerField()
|
477 |
score = models.FloatField(default=0)
|
544 |
score = models.FloatField(default=0)
|
478 |
notes = models.CharField(max_length=2000)
|
545 |
notes = models.CharField(max_length=2000)
|
479 |
|
546 |
|
480 |
def from_xml(self, xmldoc, insert = True):
|
547 |
def from_xml(self, xmldoc, instance, insert = True):
|
|
|
548 |
if not insert:
|
|
|
549 |
self.id = xmlMinidom.getNaturalAttribute(xmldoc, 'Id')
|
|
|
550 |
self.instance = instance
|
|
|
551 |
xml_question = xmldoc.getElementsByTagName('Question')[0]
|
|
|
552 |
question = Question.objects.get(pk = xmlMinidom.getNaturalAttribute(xml_question, 'Id'))
|
|
|
553 |
self.question = question
|
|
|
554 |
self.value_integer = xmlMinidom.getNaturalAttribute(xmldoc, 'ValueInteger')
|
|
|
555 |
xml_notes = xmldoc.getElementsByTagName('Notes')[0]
|
|
|
556 |
try:
|
|
|
557 |
self.notes = xml_notes.firstChild.data
|
|
|
558 |
except:
|
|
|
559 |
self.notes = ""
|
|
|
560 |
# If I am inserting I must check that there's no other answer for the same
|
|
|
561 |
# couple ('question', 'instance') as I have a unique_together constraint
|
|
|
562 |
if not self.id:
|
|
|
563 |
# I look for an answer for the same question and instance
|
|
|
564 |
try:
|
|
|
565 |
a = Answer.objects.get(instance_id=self.instance.id, question_id=self.question.id)
|
|
|
566 |
a.delete()
|
|
|
567 |
except:
|
|
|
568 |
# I didn't find one; nothing to do
|
481 |
pass
|
569 |
pass
|
|
|
570 |
self.save()
|
482 |
|
571 |
|
483 |
def to_xml(self):
|
572 |
def to_xml(self):
|
484 |
str_xml = "<Notes>" + self.notes + "</Notes>"
|
573 |
str_xml = "<Notes>" + self.notes + "</Notes>"
|
485 |
str_xml += '<Question Id="' + str(self.question.id) + '"></Question>'
|
574 |
str_xml += '<Question Id="' + str(self.question.id) + '"></Question>'
|
486 |
|
575 |
|
487 |
return '<Answer ValueInteger="' + str(self.value_integer) + '">' + str_xml + "</Answer>"
|
576 |
return '<Answer Id="' + str(self.id) + '" ValueInteger="' + str(self.value_integer) + '">' + str_xml + "</Answer>"
|
488 |
|
577 |
|
489 |
class Meta:
|
578 |
class Meta:
|
490 |
unique_together = ('question', 'instance',)
|
579 |
unique_together = ('question', 'instance',)
|
491 |
|
580 |
|
492 |
class Configuration(models.Model):
|
581 |
class Configuration(models.Model):
|
|
... |
|
... |
495 |
|
584 |
|
496 |
class UploadedFile(models.Model):
|
585 |
class UploadedFile(models.Model):
|
497 |
'''
|
586 |
'''
|
498 |
Used to save uploaded xml file so that it can be later retrieved and imported
|
587 |
Used to save uploaded xml file so that it can be later retrieved and imported
|
499 |
'''
|
588 |
'''
|
500 |
docfile = models.FileField(upload_to='documents/%Y/%m/%d') |
589 |
docfile = models.FileField(upload_to='documents/%Y/%m/%d')
|
|
|
590 |
|
|
|
591 |
class MyModel(models.Model):
|
|
|
592 |
field1 = models.CharField(max_length=40, blank=False, null=False)
|
|
|
593 |
field2 = models.CharField(max_length=60, blank=True, null=True) |