student_field_overrides.py 3.04 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
"""
API related to providing field overrides for individual students.  This is used
by the individual due dates feature.
"""
import json

from .field_overrides import FieldOverrideProvider
from .models import StudentFieldOverride


class IndividualStudentOverrideProvider(FieldOverrideProvider):
    """
    A concrete implementation of
    :class:`~courseware.field_overrides.FieldOverrideProvider` which allows for
    overrides to be made on a per user basis.
    """
    def get(self, block, name, default):
        return get_override_for_user(self.user, block, name, default)

20 21 22 23 24
    @classmethod
    def enabled_for(cls, course):
        """This simple override provider is always enabled"""
        return True

25 26 27 28 29 30 31

def get_override_for_user(user, block, name, default=None):
    """
    Gets the value of the overridden field for the `user`.  `block` and `name`
    specify the block and the name of the field.  If the field is not
    overridden for the given user, returns `default`.
    """
32
    if not hasattr(block, '_student_overrides'):
33 34
        block._student_overrides = {}  # pylint: disable=protected-access
    overrides = block._student_overrides.get(user.id)  # pylint: disable=protected-access
35 36
    if overrides is None:
        overrides = _get_overrides_for_user(user, block)
37
        block._student_overrides[user.id] = overrides  # pylint: disable=protected-access
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
    return overrides.get(name, default)


def _get_overrides_for_user(user, block):
    """
    Gets all of the individual student overrides for given user and block.
    Returns a dictionary of field override values keyed by field name.
    """
    query = StudentFieldOverride.objects.filter(
        course_id=block.runtime.course_id,
        location=block.location,
        student_id=user.id,
    )
    overrides = {}
    for override in query:
        field = block.fields[override.field]
        value = field.from_json(json.loads(override.value))
        overrides[override.field] = value
    return overrides
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89


def override_field_for_user(user, block, name, value):
    """
    Overrides a field for the `user`.  `block` and `name` specify the block
    and the name of the field on that block to override.  `value` is the
    value to set for the given field.
    """
    override, _ = StudentFieldOverride.objects.get_or_create(
        course_id=block.runtime.course_id,
        location=block.location,
        student_id=user.id,
        field=name)
    field = block.fields[name]
    override.value = json.dumps(field.to_json(value))
    override.save()


def clear_override_for_user(user, block, name):
    """
    Clears a previously set field override for the `user`.  `block` and `name`
    specify the block and the name of the field on that block to clear.
    This function is idempotent--if no override is set, nothing action is
    performed.
    """
    try:
        StudentFieldOverride.objects.get(
            course_id=block.runtime.course_id,
            student_id=user.id,
            location=block.location,
            field=name).delete()
    except StudentFieldOverride.DoesNotExist:
        pass