| 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. |