Commit ca92ffe2 by Brian Beggs

Remove SubfieldBase metaclass

parent c1292383
...@@ -13,6 +13,7 @@ file and check it in at the same time as your model changes. To do that, ...@@ -13,6 +13,7 @@ file and check it in at the same time as your model changes. To do that,
import hashlib import hashlib
import json import json
import logging import logging
import six
import uuid import uuid
from collections import OrderedDict, defaultdict, namedtuple from collections import OrderedDict, defaultdict, namedtuple
from datetime import datetime, timedelta from datetime import datetime, timedelta
...@@ -1529,7 +1530,7 @@ class CourseEnrollment(models.Model): ...@@ -1529,7 +1530,7 @@ class CourseEnrollment(models.Model):
if not status_hash: if not status_hash:
enrollments = cls.enrollments_for_user(user).values_list('course_id', 'mode') enrollments = cls.enrollments_for_user(user).values_list('course_id', 'mode')
enrollments = [(e[0].lower(), e[1].lower()) for e in enrollments] enrollments = [(six.text_type(e[0]).lower(), e[1].lower()) for e in enrollments]
enrollments = sorted(enrollments, key=lambda e: e[0]) enrollments = sorted(enrollments, key=lambda e: e[0])
hash_elements = [user.username] hash_elements = [user.username]
hash_elements += ['{course_id}={mode}'.format(course_id=e[0], mode=e[1]) for e in enrollments] hash_elements += ['{course_id}={mode}'.format(course_id=e[0], mode=e[1]) for e in enrollments]
......
...@@ -7,6 +7,8 @@ from config_models.models import ConfigurationModel ...@@ -7,6 +7,8 @@ from config_models.models import ConfigurationModel
from django.db import models from django.db import models
from django.utils.text import compress_string from django.utils.text import compress_string
from openedx.core.djangoapps.util.model_utils import CreatorMixin
logger = logging.getLogger(__name__) # pylint: disable=invalid-name logger = logging.getLogger(__name__) # pylint: disable=invalid-name
...@@ -40,12 +42,10 @@ def decompress_string(value): ...@@ -40,12 +42,10 @@ def decompress_string(value):
return ret return ret
class CompressedTextField(models.TextField): class CompressedTextField(CreatorMixin, models.TextField):
""" TextField that transparently compresses data when saving to the database, and decompresses the data """ TextField that transparently compresses data when saving to the database, and decompresses the data
when retrieving it from the database. """ when retrieving it from the database. """
__metaclass__ = models.SubfieldBase
def get_prep_value(self, value): def get_prep_value(self, value):
""" Compress the text data. """ """ Compress the text data. """
if value is not None: if value is not None:
......
...@@ -45,7 +45,7 @@ def get_problem_grade_distribution(course_id): ...@@ -45,7 +45,7 @@ def get_problem_grade_distribution(course_id):
# Loop through resultset building data for each problem # Loop through resultset building data for each problem
for row in db_query: for row in db_query:
curr_problem = UsageKey.from_string(row['module_state_key']).map_into_course(course_id) curr_problem = row['module_state_key'].map_into_course(course_id)
# Build set of grade distributions for each problem that has student responses # Build set of grade distributions for each problem that has student responses
if curr_problem in prob_grade_distrib: if curr_problem in prob_grade_distrib:
...@@ -85,7 +85,7 @@ def get_sequential_open_distrib(course_id): ...@@ -85,7 +85,7 @@ def get_sequential_open_distrib(course_id):
# Build set of "opened" data for each subsection that has "opened" data # Build set of "opened" data for each subsection that has "opened" data
sequential_open_distrib = {} sequential_open_distrib = {}
for row in db_query: for row in db_query:
row_loc = UsageKey.from_string(row['module_state_key']).map_into_course(course_id) row_loc = row['module_state_key'].map_into_course(course_id)
sequential_open_distrib[row_loc] = row['count_sequential'] sequential_open_distrib[row_loc] = row['count_sequential']
return sequential_open_distrib return sequential_open_distrib
...@@ -122,7 +122,7 @@ def get_problem_set_grade_distrib(course_id, problem_set): ...@@ -122,7 +122,7 @@ def get_problem_set_grade_distrib(course_id, problem_set):
# Loop through resultset building data for each problem # Loop through resultset building data for each problem
for row in db_query: for row in db_query:
row_loc = UsageKey.from_string(row['module_state_key']).map_into_course(course_id) row_loc = row['module_state_key'].map_into_course(course_id)
if row_loc not in prob_grade_distrib: if row_loc not in prob_grade_distrib:
prob_grade_distrib[row_loc] = { prob_grade_distrib[row_loc] = {
'max_grade': 0, 'max_grade': 0,
......
...@@ -960,7 +960,7 @@ class ScoresClient(object): ...@@ -960,7 +960,7 @@ class ScoresClient(object):
# attached to them (since old mongo identifiers don't include runs). # attached to them (since old mongo identifiers don't include runs).
# So we have to add that info back in before we put it into our lookup. # So we have to add that info back in before we put it into our lookup.
self._locations_to_scores.update({ self._locations_to_scores.update({
UsageKey.from_string(location).map_into_course(self.course_key): self.Score(correct, total, created) location.map_into_course(self.course_key): self.Score(correct, total, created)
for location, correct, total, created for location, correct, total, created
in scores_qset.values_list('module_state_key', 'grade', 'max_grade', 'created') in scores_qset.values_list('module_state_key', 'grade', 'max_grade', 'created')
}) })
......
...@@ -199,6 +199,7 @@ def issued_certificates(course_key, features): ...@@ -199,6 +199,7 @@ def issued_certificates(course_key, features):
# Report run date # Report run date
for data in generated_certificates: for data in generated_certificates:
data['report_run_date'] = report_run_date data['report_run_date'] = report_run_date
data['course_id'] = str(data['course_id'])
return generated_certificates return generated_certificates
......
...@@ -1055,7 +1055,7 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView): ...@@ -1055,7 +1055,7 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView):
CourseAccessRole.objects.filter(user=request.user, role='staff').values_list('course_id', flat=True) CourseAccessRole.objects.filter(user=request.user, role='staff').values_list('course_id', flat=True)
) )
accessible_course_ids = [item for sublist in (enrolled_courses, staff_courses) for item in sublist] accessible_course_ids = [item for sublist in (enrolled_courses, staff_courses) for item in sublist]
if requested_course_id is not None and requested_course_id not in accessible_course_ids: if requested_course_id is not None and requested_course_key not in accessible_course_ids:
return Response(status=status.HTTP_400_BAD_REQUEST) return Response(status=status.HTTP_400_BAD_REQUEST)
if not specified_username_or_team: if not specified_username_or_team:
...@@ -1068,7 +1068,7 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView): ...@@ -1068,7 +1068,7 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView):
if requested_course_key is not None: if requested_course_key is not None:
course_keys = [requested_course_key] course_keys = [requested_course_key]
elif accessible_course_ids is not None: elif accessible_course_ids is not None:
course_keys = [CourseKey.from_string(course_string) for course_string in accessible_course_ids] course_keys = accessible_course_ids
queryset = CourseTeamMembership.get_memberships(username, course_keys, team_id) queryset = CourseTeamMembership.get_memberships(username, course_keys, team_id)
page = self.paginate_queryset(queryset) page = self.paginate_queryset(queryset)
......
...@@ -551,10 +551,7 @@ class CourseOverview(TimeStampedModel): ...@@ -551,10 +551,7 @@ class CourseOverview(TimeStampedModel):
""" """
Returns all course keys from course overviews. Returns all course keys from course overviews.
""" """
return [ return CourseOverview.objects.values_list('id', flat=True)
CourseKey.from_string(course_overview['id'])
for course_overview in CourseOverview.objects.values('id')
]
def is_discussion_tab_enabled(self): def is_discussion_tab_enabled(self):
""" """
......
class Creator(object):
"""
A placeholder class that provides a way to set the attribute on the model.
"""
def __init__(self, field):
self.field = field
def __get__(self, obj, type=None):
if obj is None:
return self
return obj.__dict__[self.field.name]
def __set__(self, obj, value):
obj.__dict__[self.field.name] = self.field.to_python(value)
class CreatorMixin(object):
"""
Mixin class to provide SubfieldBase functionality to django fields.
See: https://docs.djangoproject.com/en/1.11/releases/1.8/#subfieldbase
"""
def contribute_to_class(self, cls, name, *args, **kwargs):
super(CreatorMixin, self).contribute_to_class(cls, name, *args, **kwargs)
setattr(cls, name, Creator(self))
def from_db_value(self, value, expression, connection, context):
return self.to_python(value)
...@@ -7,7 +7,7 @@ import warnings ...@@ -7,7 +7,7 @@ import warnings
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from opaque_keys.edx.keys import BlockTypeKey, CourseKey, UsageKey from opaque_keys.edx.keys import BlockTypeKey, CourseKey, UsageKey
from openedx.core.djangoapps.util.model_utils import CreatorMixin
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -68,7 +68,7 @@ def _strip_value(value, lookup='exact'): ...@@ -68,7 +68,7 @@ def _strip_value(value, lookup='exact'):
return stripped_value return stripped_value
class OpaqueKeyField(models.CharField): class OpaqueKeyField(CreatorMixin, models.CharField):
""" """
A django field for storing OpaqueKeys. A django field for storing OpaqueKeys.
...@@ -81,8 +81,6 @@ class OpaqueKeyField(models.CharField): ...@@ -81,8 +81,6 @@ class OpaqueKeyField(models.CharField):
""" """
description = "An OpaqueKey object, saved to the DB in the form of a string." description = "An OpaqueKey object, saved to the DB in the form of a string."
__metaclass__ = models.SubfieldBase
Empty = object() Empty = object()
KEY_CLASS = None KEY_CLASS = None
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment