7 import requests |
7 import requests |
8 from django.conf import settings |
8 from django.conf import settings |
9 from django.contrib.auth.models import User |
9 from django.contrib.auth.models import User |
10 from django.contrib.contenttypes.fields import GenericRelation |
10 from django.contrib.contenttypes.fields import GenericRelation |
11 from django.contrib.contenttypes.models import ContentType |
11 from django.contrib.contenttypes.models import ContentType |
12 from django.db import models, transaction |
12 from django.db import models, transaction, connection |
13 from django.utils.text import slugify |
13 from django.utils.text import slugify |
14 from django_comments_xtd.models import XtdComment |
14 from django_comments_xtd.models import XtdComment |
15 |
15 |
16 import iconolab.signals.handlers as iconolab_signals |
16 import iconolab.signals.handlers as iconolab_signals |
17 |
17 |
18 logger = logging.getLogger(__name__) |
18 logger = logging.getLogger(__name__) |
19 |
19 |
|
20 # https://docs.djangoproject.com/fr/1.11/topics/db/sql/#executing-custom-sql-directly |
|
21 def dictfetchall(cursor): |
|
22 "Return all rows from a cursor as a dict" |
|
23 columns = [col[0] for col in cursor.description] |
|
24 return [ |
|
25 dict(zip(columns, row)) |
|
26 for row in cursor.fetchall() |
|
27 ] |
20 |
28 |
21 class Collection(models.Model): |
29 class Collection(models.Model): |
22 """ |
30 """ |
23 Collection objects are the thematic item repositories in Iconolab |
31 Collection objects are the thematic item repositories in Iconolab |
24 |
32 |
40 image = models.ImageField( |
48 image = models.ImageField( |
41 upload_to='uploads/', height_field='height', width_field='width', null=True, blank=True) |
49 upload_to='uploads/', height_field='height', width_field='width', null=True, blank=True) |
42 height = models.IntegerField(null=True, blank=True) |
50 height = models.IntegerField(null=True, blank=True) |
43 width = models.IntegerField(null=True, blank=True) |
51 width = models.IntegerField(null=True, blank=True) |
44 show_image_on_home = models.BooleanField(default=False) |
52 show_image_on_home = models.BooleanField(default=False) |
|
53 completed_percent_calculated = None |
|
54 |
|
55 def completed_percent(self): |
|
56 |
|
57 if self.completed_percent_calculated is None: |
|
58 |
|
59 sql = '''SELECT i.id AS item, COUNT(a.id) AS annotations |
|
60 FROM iconolab_collection c |
|
61 JOIN iconolab_item i ON i.collection_id = c.id |
|
62 JOIN iconolab_image img ON img.item_id = i.id |
|
63 LEFT JOIN iconolab_annotation a ON a.image_id = img.id |
|
64 WHERE c.id = %s |
|
65 GROUP BY c.name, i.id''' |
|
66 |
|
67 with connection.cursor() as cursor: |
|
68 cursor.execute(sql, [self.id]) |
|
69 results = dictfetchall(cursor) |
|
70 total_items = len(results) |
|
71 items_with_annotation = 0 |
|
72 |
|
73 for result in results: |
|
74 if result['annotations'] > 0: |
|
75 items_with_annotation += 1 |
|
76 |
|
77 self.completed_percent_calculated = int(round((items_with_annotation * 100) / total_items)) |
|
78 |
|
79 return self.completed_percent_calculated |
45 |
80 |
46 def __str__(self): |
81 def __str__(self): |
47 return self.name |
82 return self.name |
48 |
83 |
49 class Folder(models.Model): |
84 class Folder(models.Model): |