Hello, As part of my GSoC work [1] I did a refactor of ForeignKey whereby I turned it into a virtual field which creates an auxiliary concrete field to hold the raw value.
As part of this, there are several changes that I did in Model._meta: 1) There are now more fields in _meta.fields, obviously. For each ForeignKey there is now an extra field with `_id` appended to its name. This extra field is not editable nor serializable, which means things like serialization, ModelForms or the admin just ignore it, however, I have no idea what other things people use _meta.fields for and it might cause problems for third-party projects. 2) I ditched _meta.virtual_fields and put all fields into local_fields instead. The reason is simple, since ForeignKey is now virtual, in a lot of places where local_fields is accessed, I'd have to search local_fields + virtual_fields. Basically, the only reason for virtual_fields that I could find was that they were cloned in each model subclass, more on this in the next item. 3) No more cloning of all virtual fields in each model subclass. Currently, each field in virtual_fields in parent models is cloned in ModelBase.__new__ and added to the subclass as a separately owned field. This is rather redundant for most virtual field types (in master that would only be GenericForeignKey and GenericRelation, in my composite-fields branch there's also ForeignKey and CompositeField). The only "field" which requires cloning is GenericRelation which needs to determine when it's accessed through a model subclass to retrieve the right content type. For other field types this is not necessary and in the case of ForeignKey it might even cause undesired effects, like multiple conflicting reverse ForeignKey pointers to a target model. Also, all related object descriptors and possibly other objects would be recreated separately for each subclass. While those should be possible to deal with, I'm still not a big fan of creating clones of objects and adding extra complexity to account for this without any real reason. Therefore, instead of cloning all virtual fields, each field class now has an attribute `clone_in_subclasses` which is True in GenericRelation and False everywhere else. Those fields with this attribute set to True will end up in private_fields instead of local_fields. To see the whole diff, check out the pull request I created [2]. I'd like people's opinions on these changes. What's the status of Model._meta? Last time I saw, it was in the state of a semi-private API -- it is not really public as it is not documented anywhere, but a LOT of people still use it in their projects because it's considered quite stable. As I said, I don't really know what people use _meta for in their projects and it's rather difficult for me to anticipate in what ways these changes can break things for them. Anssi suggested in a comment [3] to keep fields as close to the current state as possible, which means ForeignKey would appear there and the auxiliary fields it creates would not and create something like all_fields which would hold those as well. It is certainly possible to do this, but personally, I'm not really convinced -- it would mean I'd have to rewrite practically all occurrences od _meta.fields in Django to _meta.all_fields and it would introduce certain ambiguity as it would not really be clear what the difference between fields and all_fields is. So, I'd like your opinions. The more the better. Whatever the outcome, all changes will be thoroughly documented in the release notes which I'll start working on as soon as a conclusion is reached. Michal [1] https://github.com/koniiiik/django/tree/soc2013/foreignkey-refactor [2] https://github.com/django/django/pull/1407 [3] https://github.com/django/django/pull/1407#issuecomment-22092167
signature.asc
Description: Digital signature
