Gitlab CSE Unil

annotables.py 6.87 KB
Newer Older
Julien Furrer's avatar
Julien Furrer committed
1
2
3
# coding=utf-8
from __future__ import unicode_literals
import os
4
import user
Julien Furrer's avatar
Julien Furrer committed
5
6
7
8
9
10
11
import uuid, random
from django.db import models
from django.conf import settings
from django.contrib.contenttypes import generic
from django.utils.translation import ugettext as _
from django.contrib.auth.models import User
from django.utils import timezone
12
from jsonfield import JSONField
Julien Furrer's avatar
Julien Furrer committed
13
# from PIL import Image
Julien Furrer's avatar
Julien Furrer committed
14

Julien Furrer's avatar
Julien Furrer committed
15
# from sorl.thumbnail import ImageField, get_thumbnail
Julien Furrer's avatar
Julien Furrer committed
16
17
18

from eav.models import BaseEntity, BaseSchema, BaseAttribute, BaseChoice

19
__all__ = ('AOType', 'AOSchema', 'AOChoice', 'AOAttribute', 'AnObj', 'AnObjMembership')
Julien Furrer's avatar
Julien Furrer committed
20
21
22
23
24
25
26

# code from from uuid._random_getnode()
RANDOM_NODE = random.randrange(0, 1 << 48L) | 0x010000000000L

# Destination path for uploaded images, relative to MEDIA_ROOT
AO_IMAGES_PATH = 'ao_images'

Julien Furrer's avatar
Julien Furrer committed
27

Julien Furrer's avatar
Julien Furrer committed
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class AOType(models.Model):
    name = models.CharField(max_length=128)
    title = models.CharField(max_length=512, blank=True, default="")

    class Meta:
        app_label = "adim"
        verbose_name = "Annotable Object Type"

    def __unicode__(self):
        if self.title:
            return u"{} ({})".format(self.title, self.name)
        else:
            return self.name


class AOSchema(BaseSchema):
Julien Furrer's avatar
Julien Furrer committed
44
    ao_types = models.ManyToManyField(AOType, blank=True)
Julien Furrer's avatar
Julien Furrer committed
45
46
47
48
49
50

    class Meta:
        app_label = "adim"
        verbose_name = "Annotable Object Schema"
        verbose_name_plural = "Annotable Object Schemata"

51
# AOSchema._meta.get_field_by_name('datatype')[0]._choices += (('image', u'image file'), )
Julien Furrer's avatar
Julien Furrer committed
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73


class AOChoice(BaseChoice):
    schema = models.ForeignKey(AOSchema, related_name='choices')

    class Meta:
        app_label = "adim"
        verbose_name = "Annotable Object Choice"


class AOAttribute(BaseAttribute):
    schema = models.ForeignKey(AOSchema, related_name='attrs')
    choice = models.ForeignKey(AOChoice, blank=True, null=True)
    #
    value_image = models.ImageField(upload_to="ao", blank=True, null=True)

    class Meta:
        app_label = "adim"
        verbose_name = "Annotable Object Attribute"
        verbose_name_plural = "Annotable Object Attributes"


74
75
76
77
78
79
80
81
82
83
84
85
86
87
def get_image_path(instance, filename):
    now = timezone.now()
    instance.set_uuid()
    file_ext = os.path.splitext(filename)[1]
    filename = instance.uuid + file_ext
    return os.path.join(
        AO_IMAGES_PATH,
        now.strftime("%Y"),
        now.strftime("%m"),
        now.strftime("%d"),
        filename
    )


Julien Furrer's avatar
Julien Furrer committed
88
class AnObj(models.Model):
Julien Furrer's avatar
Julien Furrer committed
89
90
91
92
93
94
    """
    Annotable Object
    """
    uuid = models.CharField(max_length=32, unique=True, blank=True)

    name = models.CharField(max_length=125)
95
96
97
98
99
    owner = models.ForeignKey(User, verbose_name=_("owner"), related_name='anobjs')
    locked = models.BooleanField(verbose_name=_("locked"), default=False)

    sharing_mode = models.IntegerField(verbose_name=_("sharing mode"), default=0, blank=True)
    sharing_opts = JSONField(verbose_name=_("sharing options"), default="{}", blank=True)
100
    allow_public_publishing = models.BooleanField(verbose_name=_("allow public publishing"), default=False)
101
    members = models.ManyToManyField(User, verbose_name=_("members"), through='AnObjMembership',
Julien Furrer's avatar
Julien Furrer committed
102
                                     related_name='shared_anobjs', blank=True)
Julien Furrer's avatar
Julien Furrer committed
103

Julien Furrer's avatar
Julien Furrer committed
104
    image = models.ImageField(upload_to=get_image_path, verbose_name=_("image"), blank=True, null=True)
105
    image_url = models.CharField(max_length=512, verbose_name=_("image url"), blank=True, null=True, default="")
Julien Furrer's avatar
Julien Furrer committed
106
107
108
109

    _thumb_url = models.CharField(max_length=512, blank=True, null=True)

    # ----- eav attributes
Julien Furrer's avatar
Julien Furrer committed
110
111
112
    # ao_type = models.ForeignKey(AOType, verbose_name="type", blank=True, null=True)
    # attrs = generic.GenericRelation(AOAttribute, object_id_field='entity_id',
    #                                 content_type_field='entity_type')
Julien Furrer's avatar
Julien Furrer committed
113
114
115
116
117
118
119

    class Meta:
        app_label = "adim"
        verbose_name = "Annotable Object"
        ordering = ["-id"]

    def __unicode__(self):
Julien Furrer's avatar
Julien Furrer committed
120
121
        return u"{}".format(
            self.name
Julien Furrer's avatar
Julien Furrer committed
122
123
124
125
        )

    def save(self, *args, **kwargs):
        if not self.uuid:
126
            self.set_uuid(no_save=True)
Julien Furrer's avatar
Julien Furrer committed
127
128

        super(AnObj, self).save(*args, **kwargs)
129

Julien Furrer's avatar
Julien Furrer committed
130
131
132
        # if not self._thumb_url:
        #     self._thumb_url = self._create_thumbnail()
        #     self.save()
Julien Furrer's avatar
Julien Furrer committed
133

134
    def set_uuid(self, no_save=False):
Julien Furrer's avatar
Julien Furrer committed
135
136
137
138
139
140
141
        if not self.uuid:
            # Using the random node initialized at module level
            # to avoid compromising network address
            self.uuid = uuid.uuid1(node=RANDOM_NODE).hex
            if not no_save:
                self.save()

142
143
144
145
146
147
148
    def add_members(self, *args, **kwargs):
        """
        Add members through Membership, with specified publish mode
        """
        publish_mode = kwargs.get('publish_mode', 0)
        memberships = []
        for user in args:
149
150
151
152
153
            AnObjMembership.objects.get_or_create(anobj=self, user=user, defaults={'publish_mode': publish_mode})
        #
        #     memberships.append(AnObjMembership(anobj=self, user=user, publish_mode=publish_mode))
        # if memberships:
        #     AnObjMembership.objects.bulk_create(memberships)
154
155
156
157
158
159
160

    def remove_members(self, *args):
        """
        Remove members through Membership
        """
        AnObjMembership.objects.filter(anobj=self, user__in=args).delete()

Julien Furrer's avatar
Julien Furrer committed
161
162
163
164
165
166
167
168
169
170
171
172
173
    # def _create_thumbnail(self):
    #     if not self.image:
    #         return
    #
    #     th_path = os.path.splitext(self.image.path)[0] + "__.png"
    #     if os.path.exists(th_path):
    #         return th_path
    #
    #     im = Image.open(self.image.path)
    #     im.thumbnail(settings.ADIM_THUMB_SIZE)
    #     im.save(th_path)
    #     return th_path

Julien Furrer's avatar
Julien Furrer committed
174
175
176
    @property
    def thumb_url(self):
        if not self._thumb_url:
Julien Furrer's avatar
Julien Furrer committed
177
178
179
180
181
182
183
            # th_size = (150, 150)
            # th_path = os.path.splitext(self.image.path)[0] + "__.png"
            # im = Image.open(self.image.path)
            # im.thumbnail(th_size)
            # im.save(th_path)
            # im = get_thumbnail(self.image.name, '150x150', quality=80)
            self._thumb_url = self._create_thumbnail()
Julien Furrer's avatar
Julien Furrer committed
184
185
186
187
188
189
190
            self.save()
        return self._thumb_url

    @thumb_url.setter
    def thumb_url(self, url):
        self._thumb_url = url

Julien Furrer's avatar
Julien Furrer committed
191
192
193
194
195
196
197
    # @classmethod
    # def get_schemata_for_model(cls):
    #     return AOSchema.objects.all()
    #
    # def get_schemata_for_instance(self, qs):
    #     qs = qs.filter(models.Q(ao_types__isnull=True) | models.Q(ao_types=self.ao_type))
    #     return qs
Julien Furrer's avatar
Julien Furrer committed
198
199
200
201
202
203
204


def clear_thumbnails(qs=None):
    if qs is None or qs.model is not AnObj:
        qs = AnObj.objects.all()
    qs.update(_thumb_url="")

205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

PUBLISHING_MODES = (
    (0, _("private")),
    (1, _("owner only")),
    (2, _("all members"))
)


class AnObjMembership(models.Model):
    anobj = models.ForeignKey(AnObj)
    user = models.ForeignKey(User)
    publish_mode = models.IntegerField(choices=PUBLISHING_MODES, default=0)

    class Meta:
        app_label = "adim"
        verbose_name = "Annotable Object Membership"