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 <anssi.kaariai...@thl.fi> 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 django-developers+unsubscr...@googlegroups.com.
> To post to this group, send email to django-developers@googlegroups.com.
> 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 django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
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