7 ms·
Would you mind producing a lil' write up?
by devbug 12y ago
Would you mind producing a lil' write up?
- ubernostrum 12y agoSo, this was in the early, early days of Django with the old ORM and the old forms system (which went by the name of "manipulators"), though the bug persisted past the ORM rewrite, since it was actually in the forms system. When a "manipulator" was creating or modifying an ORM model instance, it would need to figure out which fields from the model and, sometimes, which fields from related (via foreign-key or many-to-many relations) models to include. For related models, the code would generate a dictionary, called "follow", listing the fields to, well, follow across the relation and include in the manipulator. The method "get_manipulator_fields()" on the class representing the related object would then iterate over its own fields, and if a field name turned up in the "follow" dictionary it would add that one to the under-construction list of fields for the manipulator. Except sometimes that code would crash with an exception: "AttributeError: 'bool' object has no attribute 'get'". This was rather puzzling, and although there did seem to be patterns to when it would happen, it wasn't always possible to consistently reproduce it. That two-line fix came from realizing that the exception was a symptom of an underlying problem: it was coming from a situation where the name of a foreign-key field on one model was the same as the internal-bookkeeping name Django had generated for another model class. In that case, and only in that case, the manipulator-generating code would get confused and end up on the wrong code path, which is how get_manipulator_fields() was receiving a boolean argument where it expected a dictionary (this was compounded by the fact that everything which could end up adding fields to a manipulator did so via a method of that name). So the fix was to ensure that in the code which handled related objects, Django would always use a name that couldn't conflict and throw the manipulator code down the wrong path. Of course, not long after that the manipulator system was ripped out and replaced with the much-saner django.forms module.