The idea of `QuerySet .as_manager()` sounded sane to me at first—especially in 
the light of the failure of various other attempts—but it creates a circular 
dependency between `Manager` and `QuerySet`. Creating the `Manager` class now 
requires the `QuerySet` class, and `QuerySet` needs a reference to `Manager` 
for `as_manager()`.

Is it possible to untangle this by writing a 
`Manager.from_queryset(queryset_class)` method instead? Or at least to put the 
code that creates a Manager from a QuerySet inside the Manager base class? 
QuerySet shouldn't even know what a Manager is!

I also dislike the two ad-hoc APIs spilt over the QuerySet class: the `manager` 
flag on methods and the `base_manager_class` class attribute. I'd really like 
to keep the API self-contained within the `as_manager()` or `from_queryset()` 
method.

I had started a detailed review, but I'm now thinking we should address these 
design decisions first.

-- 
Aymeric.



On 22 juil. 2013, at 10:27, Anssi Kääriäinen <[email protected]> wrote:

> Ticket #20625 deals with the problem of writing custom QuerySet methods. The 
> problem is that one needs to write some boilerplate code to have methods 
> available on both the Manager and the QuerySet. The ticket has a patch for 
> having custom QuerySet methods automatically available on the model's 
> Manager, too.
> 
> The reason for this post is that different ideas for implementing chainable 
> manager/queryset methods have been proposed multiple times. So, I want to 
> make sure we agree on the approach.
> 
> The API idea in #20625 is simple:
> 
> class MyQuerySet(models.QuerySet):
>     def published(self):
>         return self.filter(published_date__lte=now())
> 
> class MyModel(models.Model):
>     published_date = models.DateTimeField()
> 
>     objects = MyQuerySet.as_manager()
> 
> The manager created by as_manager() will automatically have a published() 
> method available. The method is created dynamically, and is effectively this:
> 
>     def published(self, *args, **kwargs):
>         getattr(self.get_query_set(), 'published')(*args, **kwargs)
> 
> The pull request contains more details. Pull request is available from 
> https://github.com/django/django/pull/1328, ticket is 
> https://code.djangoproject.com/ticket/20625.
> 
> The other proposed approaches for chainable manager methods usually use 
> overridden __getattr__() on either manager or queryset and memoizes the other 
> part's class. The __getattr__ then delegates calls to the memoized class. 
> This approach has problems with super() calls and dynamic inspection in pdb. 
> Both of those should work with the proposed approach as the created Manager 
> class really has the methods available.
> 
> Another somewhat common idea is to make Manager a QuerySet subclass and thus 
> avoid this whole Manager/QuerySet split problem. I agree on this idea, but 
> the problem is that this seems to be really hard to do in a way that is even 
> remotely backwards compatible. I tried a couple of different approaches and 
> failed miserably. If somebody has a concrete idea of how to do this, now is a 
> good time to present it.
> 
> It should be noted that the proposed patch doesn't prevent making Manager a 
> QuerySet subclass later on.
> 
> I am planning to do a final review & commit the patch soonish (likely this 
> week).
> 
>  - Anssi
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Django developers" 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.
> For more options, visit https://groups.google.com/groups/opt_out.
>  
>  

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" 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.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to