On 5/31/07, Russell Keith-Magee <[EMAIL PROTECTED]> wrote:
> However, you're not the first to propose this. In fact, I would doubt
> that you are even the tenth. This is a pretty common request.

Yeah, I know I had seen at least one mention of it before, and I
figured it was fairly common. I was just havnig trouble tracking down
any prior discussions on the topic, so I had little to go on.

> Your suggestion seems to be more on the lines of pseudo-adding the
> entire relation _model_ to the related classes:
>
> Actor.objects.filter(films__title='Fight Club')
> Actor.objects.filter(roles__role='Tyler Durden')

Admittedly, I hadn't gone far enough into it to consider how filters
like that would operate, so I'm actually fairly open to using whatever
method works best. Right now, the manager actually returns a QuerySet
based entirely on the destination model, using .extra(select=...) to
add in the fields from the join model.

It's really quite primitive at this point, since my first concern was
accessing the data from templates. Comments like yours are precisely
why I wanted to bring it to the list. :)

> This are still some namespace clash problems, but they're much smaller
> than previous suggestions, and the semantic ambiguity (i.e., the
> implication of attributes on the related model that aren't actually
> there) isn't as pronounced.

As for the namespace clash problems, I figured the manager, during its
contribute_to_class, could check the fields on each related model, and
if there are any duplicates, throw and error. That way, something like
that would fail even during 'manage.py validate'.

As for semantic ambiguity, I had given a little bit of thought to it,
and there's only so much that can be done to help that situation. The
one thing I'd insist on is that the result model (such as the Actor
taken from film.actors.filter(name='John Cleese')) would never update
the relationship when its .save() is called. That, of course, is
current functionality anyway, and I would think that changing it would
cause far too many headaches. That's why the wiki article recommends
the addition on an .update() method on the manager.

> To add to your proposal, I would say that the pseudo-attribute should
> derive its name from the relation name:
>
> Actor.objects.filter(film_roles__role='Tyler Durden')
> Film.objects.filter(actor_roles__role='Tyler Durden')
>
> Specifically, this is avoid problems when you have two m2m relations
> with a relation model (not a problem for this scenario, but certainly
> conceivable). It also has the advantage of reducing the semantic
> ambiguity a little further.

Again, I hadn't done any work yet on how filters would work, so this
seems like a reasonable approach. The manager already returns a custom
subclass of QuerySet to add in the relationship data, so adding in
extra filter behavior should be straightforward.

> Regarding syntax; Jacob's suggestion is the usual suggested syntax for
> proposals in this direction, and I'd have to say I prefer that syntax
> to your M2MManager idea. To boot, Jacob's syntax should actually fit
> into the existing contribute_to_model framework without too much
> difficulty.

I admit I hadn't considered any alternative syntax, but that's mostly
because I couldn't find any previous discussion. I'm definitely open
to alternatives, but I'll at least explain why I chose the syntax I
proposed: it falls very much in line with the existing recommendation
for defining joiner models.

The main advantage to the manager concept is that projects could
maintain all their existing models and databases, without having to
destroy anything. All they'd have to do is add the manager to
whichever models they were already using, optionally change the
related_names to make more sense, and update their other code to use
the new API. No manual schema changes would be necessary.

There is (at least) one substantial pitfall to my syntax, however.
It's fairly easy to implement basic retrieval (already done) and the
.update() method (again, already done), and the filter modifications
should be simple enough, but extending the .add() method is currently
impossible without a patch to django.db.models.fields.related.

The RelatedDescriptor subclasses the model's default manager and adds
its own .add(), so anything I put on my manager gets completely
ignored. And I'm not about to add a separate method, since that would
not only be inconsistent with other relationship types, but it would
also still leave the existing .add() in place, even though it wouldn't
function as expected.

I'm not sure how much of a patch to the RelatedDescriptor process
would need to happen to get .add() working, but it's certainly enough
of a trouble to investigate alternatives.

So, there's a bit more to chew on; hopefully we can come up with some
final thoughts on this soon, because I'd love to see this happen.

-Gul

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to