Courses have a manytoone relation to schools.
"""
import datetime
+import reversion
from django.db import models
from django.utils.text import slugify
+from django.core.urlresolvers import reverse
from karmaworld.settings.manual_unique_together import auto_add_check_unique_together
+from ajax_select import LookupChannel
+from ajax_select_cascade import DependentLookupChannel
+from ajax_select_cascade import register_channel_name
+
+from karmaworld.utils.ajax_selects import register_channel_name
class SchoolManager(models.Manager):
self.save()
+@register_channel_name('school')
+class SchoolLookup(LookupChannel):
+ """
+ Handles AJAX lookups against the school model's name and value fields.
+ """
+ model = School
+
+ def get_query(self, q, request):
+ """ Search against both name and alias. """
+ query = models.Q(name__icontains=q) | models.Q(alias__icontains=q)
+ return School.objects.filter(query)
+
+ def check_auth(self, request):
+ """ Allow anonymous access. """
+ # By default, Lookups require request.is_staff. Don't require anything!
+ pass
+
+
class DepartmentManager(models.Manager):
""" Handle restoring data. """
def get_by_natural_key(self, name, school):
super(Department, self).save(*args, **kwargs)
+@register_channel_name('dept_given_school')
+class DeptGivenSchoolLookup(DependentLookupChannel):
+ """
+ Handles AJAX lookups against the department model's name field given a
+ school.
+ """
+ model = Department
+
+ def get_dependent_query(self, q, request, dependency):
+ """ Search against department name given a school. """
+ if dependency:
+ return Department.objects.filter(name__icontains=q,
+ school__id=dependency)
+ else:
+ return []
+
+ def check_auth(self, request):
+ """ Allow anonymous access. """
+ # By default, Lookups require request.is_staff. Don't require anything!
+ pass
+
+
class ProfessorManager(models.Manager):
""" Handle restoring data. """
def get_by_natural_key(self, name, email):
objects = CourseManager()
# Core metadata
- name = models.CharField(max_length=255)
+ name = models.CharField(max_length=255, verbose_name="Course:")
slug = models.SlugField(max_length=150, null=True)
# department should remove nullable when school gets yoinked
department = models.ForeignKey(Department, blank=True, null=True)
file_count = models.IntegerField(default=0)
desc = models.TextField(max_length=511, blank=True, null=True)
- url = models.URLField(max_length=511, blank=True, null=True)
+ url = models.URLField(max_length=511, blank=True, null=True,
+ verbose_name="Course URL:")
# instructor_* is vestigial, replaced by Professor+ProfessorTaught models.
instructor_name = models.CharField(max_length=255, blank=True, null=True)
class Meta:
ordering = ['-file_count', 'school', 'name']
unique_together = ('name', 'department')
+ unique_together = ('name', 'school')
verbose_name = 'course'
verbose_name_plural = 'courses'
natural_key.dependencies = ['courses.department']
def get_absolute_url(self):
- """ return url based on school slug and self slug """
- return u"/{0}/{1}".format(self.school.slug, self.slug)
+ """ return url based on urls.py definition. """
+ return reverse('course_detail', kwargs={'slug':self.slug})
def save(self, *args, **kwargs):
""" Save school and generate a slug if one doesn't exist """
super(Course, self).save(*args, **kwargs) # generate a self.id
if not self.slug:
- self.slug = slugify(u"%s %s" % (self.name, self.id))
- self.save() # Save the slug
+ self.set_slug()
def get_updated_at_string(self):
""" return the formatted style for datetime strings """
return self.updated_at.strftime("%I%p // %a %b %d %Y")
+ def set_slug(self):
+ self.slug = slugify(u"%s %s" % (self.name, self.id))
+ self.save() # Save the slug
+
@staticmethod
def autocomplete_search_fields():
return ("name__icontains",)
self.file_count = self.note_set.count()
self.save()
+ def get_popularity(self):
+ """ Aggregate popularity of notes contained within. """
+ # Run an efficient GROUP BY aggregation within the database.
+ # It returns {'fieldname': #}, where fieldname is set in the left hand
+ # side of the aggregate kwarg. Call the field x and retrieve the dict
+ # value using that key.
+ # The value might be None, return zero in that case with shortcut logic.
+ return self.note_set.aggregate(x=models.Sum('thanks'))['x'] or 0
+
+reversion.register(Course)
class ProfessorTaughtManager(models.Manager):
""" Handle restoring data. """