| | 202 | |
| | 203 | |
| | 204 | === The Decision Process |
| | 205 | |
| | 206 | Since I started my Summer of Code project, this API has gone through several designs, and has now finalised onto the one shown above. |
| | 207 | The API has gone through many transformations. Each decision has gone through my mentor, with whom I have weekly meetings (Russell). |
| | 208 | |
| | 209 | ==== Using bitfields as flags |
| | 210 | |
| | 211 | get_field and get_fields were originally designed to work with bits. The main choice for this decision was because there were many options and, |
| | 212 | in order to avoid providing multiple flags, it would be better to provide bits. |
| | 213 | The original API for bits is: |
| | 214 | |
| | 215 | {{{ |
| | 216 | DATA = 0b00001 |
| | 217 | M2M = 0b00010 |
| | 218 | RELATED_OBJECTS = 0b00100 |
| | 219 | RELATED_M2M = 0b01000 |
| | 220 | VIRTUAL = 0b10000 |
| | 221 | |
| | 222 | # Aggregates |
| | 223 | NON_RELATED_FIELDS = DATA | M2M | VIRTUAL |
| | 224 | ALL = RELATED_M2M | RELATED_OBJECTS | M2M | DATA | VIRTUAL |
| | 225 | |
| | 226 | NONE = 0b0000 |
| | 227 | LOCAL_ONLY = 0b0001 |
| | 228 | CONCRETE = 0b0010 |
| | 229 | INCLUDE_HIDDEN = 0b0100 |
| | 230 | INCLUDE_PROXY = 0b1000 |
| | 231 | |
| | 232 | def get_fields(types, opts) |
| | 233 | }}} |
| | 234 | |
| | 235 | There are numerous reasons why we backed away from this design: |
| | 236 | 1) There is always a need to import flags from models/options, this can bring to circular dependencies |
| | 237 | 2) Importing flags all the time can also be a nuinsance |
| | 238 | 2) Importing flags is not Pythonic at all |
| | 239 | |
| | 240 | The decision taken was to port 'get_field' and 'get_fields' to flags. |
| | 241 | A port of the old implementation lies here if you are interested: https://github.com/PirosB3/django/blob/soc2014_meta_refactor_upgrade/django/db/models/options.py |
| | 242 | |
| | 243 | ==== Removed direct, m2m, model |
| | 244 | In the previous API, it was a common pattern to return model, direct (bool), m2m (bool). I soon realized that not only |
| | 245 | these three paramenters can be easily derived from a field_instance, but there were very few places that actually used some of |
| | 246 | the attributes (there is only 1 place where m2m is used). |
| | 247 | |
| | 248 | The decision taken was to drop direct, m2m, model in the return type and only keep field_instance. All the rest will be derived. |
| | 249 | |
| | 250 | ==== Removed all calls "with_model" |
| | 251 | As said previously, it is redundant to include any model as this can be derived. |
| | 252 | |
| | 253 | ==== Removed the need of multiple maps |
| | 254 | The previous implementation relied on many different cache maps internally. This is somewhat necessary, but tends to increase bug-risk |
| | 255 | when cache-expiry happens. For this reason, my implementation relies only on 2 cache tables, and I have added a specific function to do |
| | 256 | cache expiry (called _expire_cache) that will wipe out all memory. |
| | 257 | The downsides if this aspect is that we cache a bit more naively (there are less layers of caching) but benchmarks show this does not |
| | 258 | decrease performance. |