Esempio n. 1
0
class Action(models.Model):
    points_tried = models.PositiveIntegerField(default=5)
    points_incomplete = models.PositiveIntegerField(default=0)
    points_correct = models.PositiveIntegerField(default=10)
    points_correct_at_first_try = models.PositiveIntegerField(default=12)
    activity = models.ForeignKey(models.Page)
    name = models.CharField(_('name'), default="Action", max_length=200)
    short_description = delegate_to('activity')
    long_description = delegate_to('activity')

    #def __init__(self, *args, **kwargs):
    #    super().__init__(*args, **kwargs)
    #if self.activity is not None:
    #    if self.activity is None:
    #        self.activity = self.activity.specific

    def clean(self):
        super().clean()
        self.activity = self.activity.specific
        if not isinstance(self.activity, Activity):
            raise ValidationError({'activity': _('Page is not an activity!')})

    #def get_absolute_url(self):
    #return  "badge/" % self.pk
    #    return  reverse('action', args=[str(self.pk)])

    class Meta():
        verbose_name = _('action')
        verbose_name_plural = _('actions')

    title = property(lambda x: x.name)

    def __str__(self):
        return self.name
Esempio n. 2
0
class LessonPage(models.CodeschoolPage):
    """
    A single lesson in an ordered list.
    """
    class Meta:
        verbose_name = _('Lesson')
        verbose_name_plural = _('Lessons')

    body = models.StreamField([
        ('paragraph', blocks.RichTextBlock()),
    ],
                              blank=True,
                              null=True)

    description = delegate_to('lesson')
    date = delegate_to('lesson')
    calendar = property(lambda x: x.get_parent())

    # Wagtail admin
    parent_page_types = ['cs_core.CalendarPage']
    subpage_types = []
    content_panels = models.CodeschoolPage.content_panels + [
        panels.StreamFieldPanel('body'),
    ]
Esempio n. 3
0
class Calendar(models.Page):
    """
    A page that gathers a list of lessons in the course.
    """
    @property
    def course(self):
        return self.get_parent()

    weekly_lessons = delegate_to('course')

    def __init__(self, *args, **kwargs):
        if not args:
            kwargs.setdefault('title', __('Calendar'))
            kwargs.setdefault('slug', 'calendar')
        super().__init__(*args, **kwargs)

    def add_lesson(self, lesson, copy=True):
        """
        Register a new lesson in the course.

        If `copy=True` (default), register a copy.
        """

        if copy:
            lesson = lesson.copy()
        lesson.move(self)
        lesson.save()

    def new_lesson(self, *args, **kwargs):
        """
        Create a new lesson instance by calling the Lesson constructor with the
        given arguments and add it to the course.
        """

        kwargs['parent_node'] = self
        return LessonInfo.objects.create(*args, **kwargs)

    # Wagtail admin
    parent_page_types = ['courses.Course']
    subpage_types = ['courses.Lesson']
    content_panels = models.Page.content_panels + [
        panels.InlinePanel(
            'info',
            label=_('Lessons'),
            help_text=_('List of lessons for this course.'),
        ),
    ]
Esempio n. 4
0
class Lesson(models.Page):
    """
    A single lesson in an ordered list.
    """
    class Meta:
        verbose_name = _('Lesson')
        verbose_name_plural = _('Lessons')

    body = models.StreamField([
        ('paragraph', blocks.RichTextBlock()),
    ],
                              blank=True,
                              null=True)

    date = delegate_to('lesson')
    calendar = property(lambda x: x.get_parent())

    def save(self, *args, **kwargs):
        lesson = getattr(self, '_created_for_lesson', None)
        if self.pk is None and lesson is None:
            calendar = lesson.calendar
            ordering = calendar.info.values_list('sort_order', flat=True)
            calendar.lessons.add(
                Lesson(
                    title=self.title,
                    page=self,
                    sort_order=max(ordering) + 1,
                ))
            calendar.save()

    # Wagtail admin
    parent_page_types = ['courses.Calendar']
    subpage_types = []
    content_panels = models.Page.content_panels + [
        panels.StreamFieldPanel('body'),
    ]
Esempio n. 5
0
class Course(models.RoutablePageMixin, models.CodeschoolPage):
    """
    One specific occurrence of a course for a given teacher in a given period.
    """
    class Meta:
        parent_init_attribute = 'discipline'

    teachers = models.ManyToManyField(
        models.User,
        related_name='courses_as_teacher',
        blank=True,
    )
    students = models.ManyToManyField(
        models.User,
        related_name='courses_as_student',
        blank=True,
    )
    staff = models.ManyToManyField(
        models.User,
        related_name='courses_as_staff_p',
        blank=True,
    )
    weekly_lessons = models.BooleanField(
        _('weekly lessons'),
        default=False,
        help_text=_(
            'If true, the lesson spans a whole week. Othewise, each lesson '
            'would correspond to a single day/time slot.'),
    )
    accept_subscriptions = models.BooleanField(
        _('accept subscriptions'),
        default=True,
        help_text=_('Set it to false to prevent new student subscriptions.'),
    )
    is_public = models.BooleanField(
        _('is it public?'),
        default=False,
        help_text=_(
            'If true, all students will be able to see the contents of the '
            'course. Most activities will not be available to non-subscribed '
            'students.'),
    )
    subscription_passphrase = models.CharField(
        _('subscription passphrase'),
        max_length=140,
        help_text=_(
            'A passphrase/word that students must enter to subscribe in the '
            'course. Leave empty if no passphrase should be necessary.'),
        blank=True,
    )
    objects = PageManager.from_queryset(CourseQueryset)()

    short_description = delegate_to('discipline', True)
    long_description = delegate_to('discipline', True)
    short_description_html = delegate_to('discipline', True)
    long_description_html = delegate_to('discipline', True)
    lessons = property(lambda x: x.calendar_page.lessons)

    @property
    def calendar_page(self):
        content_type = models.ContentType.objects.get(app_label='cs_core',
                                                      model='calendarpage')
        return apps.get_model('cs_core', 'CalendarPage').objects.get(
            depth=self.depth + 1,
            path__startswith=self.path,
            content_type_id=content_type,
        )

    @property
    def questions_page(self):
        content_type = models.ContentType.objects.get(app_label='cs_questions',
                                                      model='questionlist')
        return apps.get_model('cs_questions', 'QuestionList').objects.get(
            depth=self.depth + 1,
            path__startswith=self.path,
            content_type_id=content_type,
        )

    @property
    def gradables_page(self):
        content_type = models.ContentType.objects.get(app_label='cs_core',
                                                      model='gradablespage')
        return apps.get_model('cs_core', 'GradablesPage').objects.get(
            depth=self.depth + 1,
            path__startswith=self.path,
            content_type_id=content_type,
        )

    @property
    def discipline(self):
        return self.get_parent().specific

    @discipline.setter
    def discipline(self, value):
        self.set_parent(value)

    @property
    def questions(self):
        return self.questions_page.questions

    def add_question(self, question, copy=True):
        """
        Register a new question to the course.

        If `copy=True` (default), register a copy.
        """

        self.questions.add_question(question, copy)

    def new_question(self, cls, *args, **kwargs):
        """
        Create a new question instance by calling the cls with the given
        arguments and add it to the course.
        """

        self.questions.new_question(cls, *args, **kwargs)

    def add_lesson(self, lesson, copy=True):
        """
        Register a new lesson in the course.

        If `copy=True` (default), register a copy.
        """

        self.lessons.add_lesson(lesson, copy)

    def new_lesson(self, *args, **kwargs):
        """
        Create a new lesson instance by calling the Lesson constructor with the
        given arguments and add it to the course.
        """

        self.lessons.new_lesson(*args, **kwargs)

    def register_student(self, student):
        """
        Register a new student in the course.
        """

        self.students.add(student)
        self.update_friendship_status(student)

    def update_friendship_status(self, student=None):
        """
        Recompute the friendship status for a single student by marking it as
        a colleague of all participants in the course..

        If no student is given, update the status of all enrolled students.
        """

        update = self._update_friendship_status
        if student is None:
            for student in self.students.all():
                update(student)
        else:
            update(student)

    def _update_friendship_status(self, student):
        # Worker function for update_friendship_status
        colleague_status = FriendshipStatus.STATUS_COLLEAGUE
        for colleague in self.students.all():
            if colleague != student:
                try:
                    FriendshipStatus.objects.get(owner=student,
                                                 other=colleague)
                except FriendshipStatus.DoesNotExist:
                    FriendshipStatus.objects.create(owner=student,
                                                    other=colleague,
                                                    status=colleague_status)

    def get_absolute_url(self):
        return url_reverse('course-detail', args=(self.pk, ))

    def get_user_role(self, user):
        """Return a string describing the most privileged role the user
        as in the course. The possible values are:

        teacher:
            Owns the course and can do any kind of administrative tasks in
            the course.
        staff:
            Teacher assistants. May have some privileges granted by the teacher.
        student:
            Enrolled students.
        visitor:
            Have no relation to the course. If course is marked as public,
            visitors can access the course contents.
        """

        if user == self.teacher:
            return 'teacher'
        if user in self.staff.all():
            return 'staff'
        if user in self.students.all():
            return 'student'
        return 'visitor'

    def get_user_activities(self, user):
        """
        Return a sequence of all activities that are still open for the user.
        """

        activities = self.activities.filter(status=Activity.STATUS_OPEN)
        return activities.select_subclasses()

    def activity_duration(self):
        """
        Return the default duration (in minutes) for an activity starting from
        now.
        """

        return 120

    def next_time_slot(self):
        """Return the start and end times for the next class in the course.

        If a time slot is currently open, return it."""

        now = timezone.now()
        return now, now + timezone.timedelta(self.activity_duration())

    def next_date(self, date=None):
        """Return the date of the next available time slot."""

    def can_view(self, user):
        return user != annonymous_user()

    def can_edit(self, user):
        return user in self.teachers.all() or user == self.owner

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, *args, **kwargs)
        context['activities'] = self.questions
        return context

    # Wagtail admin
    parent_page_types = ['cs_core.Discipline']
    subpage_types = []
    content_panels = Page.content_panels + [
        panels.InlinePanel(
            'time_slots',
            label=_('Time slots'),
            help_text=_('Define when the weekly classes take place.'),
        ),
    ]
    settings_panels = Page.settings_panels + [
        panels.MultiFieldPanel([
            panels.FieldPanel('weekly_lessons'),
            panels.FieldPanel('is_public'),
        ],
                               heading=_('Options')),
        panels.MultiFieldPanel([
            panels.FieldPanel('accept_subscriptions'),
            panels.FieldPanel('subscription_passphrase'),
        ],
                               heading=_('Subscription')),
    ]
Esempio n. 6
0
class UserMixin:
    # Delegate profile properties
    about_me = delegate_to('profile')
    date_of_birth = delegate_to('profile')
    gender = delegate_to('profile')
    nickname = delegate_to('profile')
    phone = delegate_to('profile')
    school_id = delegate_to('profile')
    website = delegate_to('profile')
    mugshot = delegate_to('profile')

    @property
    def profile(self):
        try:
            return self._profile
        except Profile.DoesNotExist:
            return Profile.objects.create(user=self)

    @property
    def is_student(self):
        return ...

    @property
    def is_teacher(self):
        return ...

    def _filtered(self, status):
        pks = (self.related_users.filter(status=status).values_list('other',
                                                                    flat=True))
        return models.User.objects.filter(pk__in=pks).order_by(
            'first_name', 'username')

    @property
    def friends(self):
        """A queryset with all the users's friends."""

        return self._filtered('friend')

    @property
    def unfriends(self):
        """A queryset with all users the that were un-friended by the current
        user."""

        return self._filtered('unfriend')

    @property
    def friends_pending(self):
        """A queryset with users that have a pending friendship request
        waiting to be accepted or rejected."""

        return self._filtered('pending')

    def _multi_select(self, field):
        courses = list(self.enrolled_courses.all())
        if not courses:
            return []
        first, *tail = courses
        users = getattr(first, field).all()
        for course in tail:
            users |= getattr(course, field).all()
        users = users.exclude(pk=self.pk)
        return users.order_by('first_name', 'username').distinct()

    @property
    def colleagues(self):
        """A queryset of all user's colleagues."""

        return self._multi_select('students')

    @property
    def staff_contacts(self):
        """A queryset of all staff members to the user's courses."""

        return self._multi_select('staff')

    @property
    def teacher_contacts(self):
        """A queryset of all teachers in the user's enrolled courses."""

        pks = self.enrolled_courses.values_list('teacher', flat=True)
        return models.User.objects.filter(pk__in=pks).distinct()

    def get_absolute_url(self):
        return self.profile.url
Esempio n. 7
0
class Profile(UserenaBaseProfile, models.CodeschoolPage):
    """
    Social information about users.
    """
    class Meta:
        permissions = (
            ('student', _('Can access/modify data visible to student\'s')),
            ('teacher',
             _('Can access/modify data visible only to Teacher\'s')),
        )

    username = delegate_to('user', True)
    first_name = delegate_to('user')
    last_name = delegate_to('user')
    email = delegate_to('user')

    @property
    def short_description(self):
        return '%s (id: %s)' % (self.get_full_name_or_username(),
                                self.school_id)

    @property
    def age(self):
        if self.date_of_birth is None:
            return None
        today = timezone.now().date()
        return int(round((today - self.date_of_birth).years))

    user = models.OneToOneField(
        models.User,
        unique=True,
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        verbose_name=_('user'),
        related_name='_profile',
    )
    school_id = models.CharField(
        _('school id'),
        help_text=_('Identification number in your school issued id card.'),
        max_length=50,
        blank=True,
        null=True)
    nickname = models.CharField(max_length=50, blank=True, null=True)
    phone = models.CharField(max_length=20, blank=True, null=True)
    gender = models.SmallIntegerField(_('gender'),
                                      choices=[(0, _('male')),
                                               (1, _('female'))],
                                      blank=True,
                                      null=True)
    date_of_birth = models.DateField(_('date of birth'), blank=True, null=True)
    website = models.URLField(blank=True, null=True)
    about_me = models.RichTextField(blank=True, null=True)
    objects = ProfileManager.from_queryset(models.PageManager)()

    def __init__(self, *args, **kwargs):
        if 'user' in kwargs and 'id' not in kwargs:
            kwargs.setdefault('parent_page', profile_root())
        super().__init__(*args, **kwargs)

        if self.pk is None and self.user is not None:
            user = self.user
            self.title = self.title or __("%(name)s's profile") % {
                'name': user.get_full_name() or user.username
            }
            self.slug = self.slug or user.username.replace('.', '-')

    def __str__(self):
        if self.user is None:
            return __('Unbound profile')
        full_name = self.user.get_full_name() or self.user.username
        return __('%(name)s\'s profile') % {'name': full_name}

    def get_full_name_or_username(self):
        name = self.user.get_full_name()
        if name:
            return name
        else:
            return self.user.username

    # Wagtail admin
    parent_page_types = ['cs_core.ProfileRoot']
    content_panels = models.CodeschoolPage.content_panels + [
        panels.MultiFieldPanel([
            panels.FieldPanel('school_id'),
        ],
                               heading='Required information'),
        panels.MultiFieldPanel([
            panels.FieldPanel('nickname'),
            panels.FieldPanel('phone'),
            panels.FieldPanel('gender'),
            panels.FieldPanel('date_of_birth'),
        ],
                               heading=_('Personal Info')),
        panels.MultiFieldPanel([
            panels.FieldPanel('website'),
        ],
                               heading=_('Web presence')),
        panels.RichTextFieldPanel('about_me'),
    ]
Esempio n. 8
0
 class A:
     bar = delegate_to('foo')