Proposed usability improvements for django key fields
Two proposed changes to make `UsageKeyField` and friends more useful:
1. Give each of `UsageKeyField` and friends a sensible `max_length` default to DRY up model definitions. Currently we put `max_length=255` in every single model definition where these are used. In addition, use a shorter default length which is compatible with InnoDB indexing when the `utf8mb4` character set is used regardless of the MySQL index length configuration. IMHO any new IDAs we make should be using `utf8mb4` for their entire DB, so the default length should be compatible.
1. It's currently a common pattern to have both a `course_id` field and a `usage_id` field in order to get indexed lookups by course. However, for almost four years we've been using usage keys which have the course ID at the beginning of the serialized usage key value, so it's possible to use only a single indexed `usage_id` column and still query by course using `WHERE usage_key LIKE 'block-v1:COURSE_ID_HERE%'` just as efficiently as if course_id was materialized in its own column and index. With this change, you can create a model that only has a usage_id field and then query by course using the `Model.objects.filter(usage_key__course=self.course_key)` lookup.
Tradeoffs of #2 are:
Simplifies data model
Reduces table/index size somewhat by removing redundant data
Improves data integrity (derived course_id will always correspond to usage_id) - we have observed such a column mismatch bug in the wild on at least one occasion
But it doesn't support old mongo keys
It places the constraint on new UsageKey formats that they must encode the course ID in the usage key serialized form in order to be compatible.
Doesn't support `usage_id_course_in=[list of course IDs]` though that could be added later.
Prevents `GROUP BY course_id` clauses
Install in your LMS devstack container, then run something like the following from the LMS django shell:
from courseware.models import StudentModule
obj = StudentModule.objects.all()
course_key = obj.course_id