On Tue, 2014-08-05 at 16:26 +0200, Loic Bistuer wrote:
> Hi Daniel,
>
> I'm a little confused because if I understand correctly you introduced the concept of "data" field that you describe as "any field that has an entry on the database", but how is that different from the earlier concept of "concrete" fields.
>
> For now FO, FK and O2O all fall under the "concrete" fields category but my take is that eventually all relations should be "virtual", some of them relying on one or more concrete fields (i.e. composite). Currently virtual fields are not part of the public API, and IIRC they are not allowed to have form fields. Eventually we'll need the concept of "data" fields that span a subset of both concrete and virtual fields of a given model for the purpose of acquiring and presenting data (i.e. forms or admin). For instance:
>
> class Model:
> name = model.CharField() # concrete & data
> fk_col1 = models.IntegerField() # concrete only
> fk_col2 = models.IntegerField() # concrete only
> fk = models.ForeignKey(col1, col2) # virtual & data
This categorization seems very good.
GenerigForeignKey behaves a bit differently from the other virtual field
we have in core (that is, ForeignObject). GenerigForeignKeys can't be
used in ORM lookups in select_related(), values() or in filters. This is
one corner case which isn't covered by the above distinction. Adding
support for filtering is a TODO, but select_related and values do not
make sense (as we would also need to do select_related in that case). I
guess we just have to exclude some/all virtual fields by their
properties in ORM methods, where different ORM methods allow different
subsets of virtual fields to be used.
In addition, we have an interesting case in model initialization where
ForeignObjects can be used in model initialization when used as a
keyword argument, but not when used as positional argument. This makes
sense when considering the use cases - positional arguments are (mostly)
used as a fast path when initializing models from database. And, when
initializing the model from database, there are only concrete fields
present.
GFKs can't be used in kwargs model initialization, but ForeignObjects
can be used (currently ForeignObject is in meta.fields, but not in
concrete_fields, whereas GFKs are in virtual_fields but not in
fields...). I don't see a reason why we couldn't add support for GFKs in
model init kwargs, too. This way we could move ForeignObject to the new
API's virtual fields category, and make virtual_fields a subset of all
fields.
In summary I think we could try categorization to concrete, virtual and
data fields. Concrete fields are those that have backing database
columns, virtual fields do not have database columns, and data fields
are fields that present data to users. Unfortunately it is hard to say
if this categorization is sufficient without trying.
- Anssi