from django.core.files.storage import FileSystemStorage
from django.db import models
from django.template import defaultfilters
+import django_filepicker
from lxml.html import fromstring, tostring
from oauth2client.client import Credentials
from taggit.managers import TaggableManager
fs = FileSystemStorage(location=settings.MEDIA_ROOT)
-class Note(models.Model):
+class Document(models.Model):
+ """ An Abstract Base Class representing a document
+ intended to be subclassed
+
+ """
+ course = models.ForeignKey(Course)
+ tags = TaggableManager(blank=True)
+ name = models.CharField(max_length=255, blank=True, null=True)
+ slug = models.SlugField(max_length=255, null=True)
+
+ # metadata relevant to the Upload process
+ ip = models.IPAddressField(blank=True, null=True,
+ help_text=u"IP address of the uploader")
+ uploaded_at = models.DateTimeField(null=True, default=datetime.datetime.utcnow)
+
+
+ # if True, NEVER show this file
+ # WARNING: This may throw an error on migration
+ is_hidden = models.BooleanField(default=False)
+
+ fp_note = django_filepicker.models.FPFileField(
+ upload_to='queue/%Y/%m/%j/',
+ null=True, blank=True,
+ help_text=u"An uploaded file reference from Filepicker.io")
+
+ class Meta:
+ abstract = True
+ ordering = ['-uploaded_at']
+
+
+ def __unicode__(self):
+ return u"Document: {1} -- {2}".format(self.name, self.uploaded_at)
+
+ def _generate_unique_slug(self):
+ """ generate a unique slug based on name and uploaded_at """
+ _slug = defaultfilters.slugify(self.name)
+ klass = self.__class__
+ collision = klass.objects.filter(slug=self.slug)
+ if collision:
+ _slug = u"{0}-{1}-{2}-{3}".format(
+ _slug, self.uploaded_at.month,
+ self.uploaded_at.day, self.uploaded_at.microsecond)
+ self.slug = _slug
+
+ def save(self, *args, **kwargs):
+ if self.name and not self.slug:
+ self._generate_unique_slug()
+ super(Document, self).save(*args, **kwargs)
+
+class Note(Document):
""" A django model representing an uploaded file and associated metadata.
"""
+ # FIXME: refactor file choices after FP.io integration
UNKNOWN_FILE = '???'
FILE_TYPE_CHOICES = (
('doc', 'MS Word compatible file (.doc, .docx, .rtf, .odf)'),
(UNKNOWN_FILE, 'Unknown file'),
)
- course = models.ForeignKey(Course)
- # Tagging system
- tags = TaggableManager(blank=True)
-
- name = models.CharField(max_length=255, blank=True, null=True)
- slug = models.SlugField(max_length=255, null=True)
- year = models.IntegerField(blank=True, null=True,
- default=datetime.datetime.utcnow().year)
- desc = models.TextField(max_length=511, blank=True, null=True)
- uploaded_at = models.DateTimeField(null=True, default=datetime.datetime.utcnow)
-
- file_type = models.CharField(max_length=15,
- choices=FILE_TYPE_CHOICES,
- default=UNKNOWN_FILE,
+ file_type = models.CharField(max_length=15, \
+ choices=FILE_TYPE_CHOICES, \
+ default=UNKNOWN_FILE, \
blank=True, null=True)
# Upload files to MEDIA_ROOT/notes/YEAR/MONTH/DAY, 2012/10/30/filename
# FIXME: because we are adding files by hand in tasks.py, upload_to is being ignored for media files
- note_file = models.FileField(
- storage=fs,
- upload_to="notes/%Y/%m/%j/",
+ pdf_file = models.FileField( \
+ storage=fs, \
+ upload_to="notes/%Y/%m/%j/",\
blank=True, null=True)
- pdf_file = models.FileField(
- storage=fs,
- upload_to="notes/%Y/%m/%j/",
+ # No longer keeping a local copy backed by django
+ note_file = models.FileField( \
+ storage=fs, \
+ upload_to="notes/%Y/%m/%j/",\
blank=True, null=True)
- ## post gdrive conversion data
+ # Google Drive URLs
embed_url = models.URLField(max_length=1024, blank=True, null=True)
download_url = models.URLField(max_length=1024, blank=True, null=True)
- # for word processor documents
+
+ # Generated by Google Drive by saved locally
html = models.TextField(blank=True, null=True)
text = models.TextField(blank=True, null=True)
- # if True, NEVER show this file
- draft = models.BooleanField(default=False)
+ # not using, but keeping old data
+ year = models.IntegerField(blank=True, null=True,\
+ default=datetime.datetime.utcnow().year)
+ desc = models.TextField(max_length=511, blank=True, null=True)
- class Meta:
- """ Sort files by most recent first """
- ordering = ['-uploaded_at']
+ is_flagged = models.BooleanField(default=False)
+ is_moderated = models.BooleanField(default=False)
def __unicode__(self):
- return u"{0}: {1} -- {2}".format(self.file_type, self.name, self.uploaded_at)
+ return u"Note: {0} {1} -- {2}".format(self.file_type, self.name, self.uploaded_at)
- def save(self, *args, **kwargs):
- """ override built-in save to ensure contextual self.name """
- # TODO: If self.name isn't set, generate one based on uploaded_name
- # if we fail to set the Note.name earlier than this, use the saved filename
-
- # only generate a slug if the name has been set, and slug hasn't
- if not self.slug and self.name:
- slug = defaultfilters.slugify(self.name)
- cursor = Note.objects.filter(slug=slug)
- # If there are no other notes with this slug, then the slug does not need an id
- if cursor.count() == 0:
- self.slug = slug
- else:
- super(Note, self).save(*args, **kwargs) # generate self.id
- self.slug = defaultfilters.slugify("%s %s" % (self.name, self.id))
- super(Note, self).save(*args, **kwargs)
-
- # Check if Note.uploaded_at is after Course.updated_at
- if self.uploaded_at and self.uploaded_at > self.course.updated_at:
- self.course.updated_at = self.uploaded_at
- # if it is, update Course.updated_at
- self.course.save()
-
- super(Note, self).save(*args, **kwargs)
def get_absolute_url(self):
""" Resolve note url, use 'note' route and slug if slug
self.save()
return True, len(a_tags)
+ def _update_parent_updated_at(self):
+ """ update the parent Course.updated_at model
+ with the latest uploaded_at """
+ self.course.updated_at = self.uploaded_at
+ self.course.save()
+
+ def save(self, *args, **kwargs):
+ if self.uploaded_at and self.uploaded_at > self.course.updated_at:
+ self._update_parent_updated_at()
+ super(Note, self).save(*args, **kwargs)
class DriveAuth(models.Model):