I've started doing some refactorings to the fields/related.py. The ultimate 
goal is to have field.rel (ForeignObjectRel) instances to be Field 
subclasses.

I first went ahead and did exactly this with the idea of changing 
everything in one go. Turns out this was a bad idea, after around 1700 
lines changed everything was broken and there were multiple hard to debug 
failures.

I did a fresh start, and my plan is now to do the following:
  - First, make ForeignObjectRel to act like a Field instance (part of this 
is done in https://github.com/django/django/pull/4241)
  - Make ForeignObjectRel Field subclass. This will likely rename the 
classes to something like ReverseForeignKey, ReverseManyToMany and so on.
  - Finally, add the new reverse field instances directly to the remote 
model's _meta

This is just clean-up in the fields/related.py. The composite fields work 
doesn't need to rely on this. To get to a state where we have composite 
primary keys and composite joins we should:
  - Split ForeignKey to a concrete field instance, and a related field 
instance. After this all related fields are purely virtual. This means that 
author = models.ForeignKey(Author) will automatically generate a author_id 
= IntegerField() on the model. Unfortunately this also means model._meta 
will now contains two fields for each foreign key defined on the model 
instead of just one.
  - Add composite fields (but not yet composite foreign keys or primary 
keys)
  - Add composite primary keys
  - Add composite foreign keys

Addition of composite fields can be done at the same time with changes to 
fields/related.py, so it should be possible to start working on composite 
fields right away.

Michal Petrucha did a lot of work to add composite fields to Django. The 
syntax he had was:

class MyModel(models.Model):
    x = models.IntegerField()
    y = models.IntegerField()
    point = models.CompositeField(x, y)

I think we should stick to that.

It is essential that we don't try to do too much in one go. Even small 
changes tend to be hard to do. Trying to do all this in one go will result 
in a patch that will be nearly impossible to review, and which will 
conflict badly with other changes once finished.

If you want to work on the composite fields part of this, I suggest you 
should take a close look at what was done in Petrucha's GSoC work 
(https://github.com/koniiiik/django/, unfortunately I don't recall which 
branch contains the latest code). The code got to a point where it was 
pretty much commit ready. The commit didn't happen because migrations were 
getting ready for merge at the same time, and committing Petrucha's work 
would have caused severe problems for migrations.

The first part in the composite fields work should be making the point 
field example to work. This will mean supporting .filter(point__in=((1, 2), 
(2, 3))), and support for .values('point'). Both of these will be 
surprisingly complex to do correctly. In addition there will likely be a 
lot of work to do in other parts of Django, too (for example in 
migrations), so implementing just "simple" composite fields will be a lot 
of work.

I like the MoneyField idea, but lets punt composite field definitions in 
that way for later.

 - Anssi

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/673dc9ed-da09-46d5-902e-311756613c81%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to