models.py 2.97 KB
Newer Older
1 2 3
from django.db import models
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
4
from django.core.exceptions import ValidationError
5
from django.utils.html import strip_tags
6 7
import json

Arthur Barrett committed
8

9 10 11
class Note(models.Model):
    user = models.ForeignKey(User, db_index=True)
    course_id = models.CharField(max_length=255, db_index=True)
12
    uri = models.CharField(max_length=255, db_index=True)
13 14
    text = models.TextField(default="")
    quote = models.TextField(default="")
15
    range_start = models.CharField(max_length=2048)  # xpath string
16
    range_start_offset = models.IntegerField()
17
    range_end = models.CharField(max_length=2048)  # xpath string
18
    range_end_offset = models.IntegerField()
Arthur Barrett committed
19
    tags = models.TextField(default="")  # comma-separated string
20 21
    created = models.DateTimeField(auto_now_add=True, null=True, db_index=True)
    updated = models.DateTimeField(auto_now=True, db_index=True)
22 23

    def clean(self, json_body):
e0d committed
24
        """
25
        Cleans the note object or raises a ValidationError.
e0d committed
26
        """
27 28 29 30 31 32 33
        if json_body is None:
            raise ValidationError('Note must have a body.')

        body = json.loads(json_body)
        if not type(body) is dict:
            raise ValidationError('Note body must be a dictionary.')

34 35 36 37 38 39
        # NOTE: all three of these fields should be considered user input
        # and may be output back to the user, so we need to sanitize them.
        # These fields should only contain _plain text_.
        self.uri = strip_tags(body.get('uri', ''))
        self.text = strip_tags(body.get('text', ''))
        self.quote = strip_tags(body.get('quote', ''))
40 41 42 43 44 45 46 47 48 49 50

        ranges = body.get('ranges')
        if ranges is None or len(ranges) != 1:
            raise ValidationError('Note must contain exactly one range.')

        self.range_start = ranges[0]['start']
        self.range_start_offset = ranges[0]['startOffset']
        self.range_end = ranges[0]['end']
        self.range_end_offset = ranges[0]['endOffset']

        self.tags = ""
51
        tags = [strip_tags(tag) for tag in body.get('tags', [])]
52 53
        if len(tags) > 0:
            self.tags = ",".join(tags)
54 55

    def get_absolute_url(self):
e0d committed
56
        """
e0d committed
57
        Returns the absolute url for the note object.
e0d committed
58
        """
59
        kwargs = {'course_id': self.course_id, 'note_id': str(self.pk)}
60 61 62
        return reverse('notes_api_note', kwargs=kwargs)

    def as_dict(self):
e0d committed
63
        """
64
        Returns the note object as a dictionary.
e0d committed
65
        """
66
        return {
67 68
            'id': self.pk,
            'user_id': self.user.pk,
69 70 71 72 73 74 75 76 77
            'uri': self.uri,
            'text': self.text,
            'quote': self.quote,
            'ranges': [{
                'start': self.range_start,
                'startOffset': self.range_start_offset,
                'end': self.range_end,
                'endOffset': self.range_end_offset
            }],
78 79 80
            'tags': self.tags.split(","),
            'created': str(self.created),
            'updated': str(self.updated)
Arthur Barrett committed
81
        }