def get(self, *args, **kwargs):
if not hasattr(self, '_cache'):
self._cache = # build a dictself.all())
return self._cache.get(...)
This was working for every some_object.city event across requests. Now
it doesn't work because parent is not accessed through custom manager.
For now I can't propose any nice solution apart from backing out that
revision because it needs to be reworked.
I don't need an explanation why my code doesn't work :-). For that
matter I was the one who was objecting to this change because "managers
are used not only for filtering".
So I want to solve the problem, not document that it's insolvable.
Looks like I've got something that could work...
Manager class should have a separate method get_full_query_set() that
will return an unfiltered queryset. Current get_query_set() will just
call get_full_query_set() by default. This way users could override
get_full_query_set however they like but it will be required to return
all records. get_query_set() will remain a "filtering point".
Overriding Manager.get still won't work as it was working before but at
least we will be able to subclass a QuerySet, override "get" there and
return this QuerySet from get_full_query_set()
/me went away to write a patch...
I was arguing for reverting r8017 and wontfixing the issue that
caused it (#7666).
That would have solved your problem.
Unfortunatelly "default manager" is not as clearly defined as I hoped.
>
> >
It doesn't have to *restrict* a queryset. Here's a usecase (it might
seem boring but it's real). I have a forum where Article refers to User
and Profile refers to User. I want Articles selected with their Users
*and* their Profiles. select_related() would fetch Users just fine but
it won't fetch their Profiles because it's a reverse relation (Profiles
refers to Users). So I subclass a QuerySet with ArticleQuerySet where I
have one additional query for Profiles which I then just assign to their
Articles. This is where I have a manager whose get_query_set() returns
ArticleQuerySet instead of standard QuerySet. It's not restricted but
rather "enhanced".
Ah, I see now, thanks for clarification. However the issue that caused
#7666 is also real and I think it should be fixed also. I have proposed
a solution (though not perfect) elsewhere in the thread.
That's fine. Then you don't have problems as in #7666, #2698, or
#7566. I understand that overriding get_query_set() is useful, I do
that myself. But if you want subsets of your data, I think you're
better off providing a filter method on a custom QuerySet class and
optionally providing a proxy on your manager for consistency. That
gives you more flexibility (http://dpaste.com/hold/67035/) and
bypasses the problems in the mentioned tickets.
>
> >
Actually I didn't... I still won't to invent some way of preserving
current behavior where we use manager instance to store a cache that
"get" uses. I'm thinking of something along the lines `Manager.get(self,
use_full_queryset=False)` for all proxy methods. Or may be really having
a pre-defined separate `all_objects` property on a model for a second
manager with full results... If anyone have any ideas don't hesitate to
share!
I provided this example just because you asked what people can do apart
from filtering.
My current problem is described in first post of the thread: accessing
`child.parent` doesn't call Parent.objects.get. It's not #7666 by itself
it's just mentioned there in comments.
Hello!
I've managed to come to agreement with all talking voices in my head and
come up with a patch[1] that seems sane to me. The solution is explained
in the ticket an I ask someone of the triagers or core devs to take a
look at it when you have time.
Thanks!
I'm not very fond of "get_full" either :-). The reason is since I have
"get_full_query_set" (which is OK since we already have
get_empty_query_set) then "get_full" should point that it's different
from "get" by accessing "get_full_query_set". But in the context of
calling it looks strange indeed. For alternatives:
- get_unfiltered
- unfiltered_get
- get_from_full
- get_for_parent (but it restricts its usage)
?
super(SomeManagerClass, self).get_query_set()
And you're done.
--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."
No, James, you're missing the point here. This will bypass custom
manager entirely and will use queryset instance directly. This is how it
works now (after #7666) and this is what we want to fix. We want to be
able to override a method on a manager that will be called when looking
up parent object. In the old days before #7666 it was {{{get}}}. Now it
won't work because {{{get}}} uses a queryeset pre-filtered by custom
{{{get_query_set}}}. This is why I'm introducing a new method that a)
uses unfiltered queryset and b) can be overridden.
--
----
Waylan Limberg
way...@gmail.com
For some reason I didn't receive email from Trac saying about this
commit... Anyway, this looks strange because Jacob has applied the first
patch (by Justin Bronn) instead of the second one (by me) though
everyone (including Justin) seem to agree that the second approach is
better.
Jacob, can you explain the reason? My own concerns about the approach
with switching attribute are explained in the ticket[1].
I'm not thrilled with adding more methods onto the manager; further,
what happens if someone filters get_full_query_set()? Do we then need
to add a get_really_full_query_set_no_I_mean_it_this_time()? The same
reasoning applies to adding methods to QuerySet itself.
Further, what, exactly, does "full" mean? Someone who's followed this
issue likely understands well enough, but most people won't; it's Yet
Another API Method to learn.
Finally, this is at best a stop-gap: the current handling of related
managers is badly designed, and due for a refactor. So I did the
simplest thing that could possibly work so that we can get 1.0 out on
time.
Jacob
Not to argue but for the sake of completeness... It's the same situation
if someone, say, returns a string from get_query_set. In other words,
yes, if someone doesn't follow documentation Bad Staff happens :-)
> Finally, this is at best a stop-gap: the current handling of related
> managers is badly designed, and due for a refactor.
Fair enough. Thanks for the explanation...