[Question] Why BaseManager._get_queryset_methods need use getattr(self.get_queryset(), name) in create_method

97 views
Skip to first unread message

Ryoma Han

unread,
Feb 27, 2024, 7:28:05 PMFeb 27
to Django developers (Contributions to Django itself)
I've been reading through the Django source code the last few days. When I was reading the BaseManager source code I saw a method like this:

```python
    @classmethod
    def _get_queryset_methods(cls, queryset_class):
        def create_method(name, method):
            @wraps(method)
            def manager_method(self, *args, **kwargs):
                return getattr(self.get_queryset(), name)(*args, **kwargs)

            return manager_method

        new_methods = {}
        for name, method in inspect.getmembers(
            queryset_class, predicate=inspect.isfunction
        ):
            if hasattr(cls, name):
                continue
            queryset_only = getattr(method, "queryset_only", None)
            if queryset_only or (queryset_only is None and name.startswith("_")):
                continue
            new_methods[name] = create_method(name, method)
        return new_methods
```

My question is why we use `getattr(self.get_queryset(), name)` insted of just use `method`.

Tim Graham

unread,
Feb 27, 2024, 9:13:09 PMFeb 27
to Django developers (Contributions to Django itself)
Hi Ryoma, a good way to investigate this would be to make the change and see if anything breaks. 

If I understand correctly, your suggest is:

-                return getattr(self.get_queryset(), name)(*args, **kwargs)
+                return method(*args, **kwargs)

In that case, running the test suite gives this error:

  File "/home/tim/code/django/django/db/models/manager.py", line 89, in manager_method
    return method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^
TypeError: QuerySet.using() missing 1 required positional argument: 'alias'

I leave further investigation to you. :-)

Ryoma Han

unread,
Feb 29, 2024, 7:36:29 AMFeb 29
to Django developers (Contributions to Django itself)
Thanks for your answer. I will continue to investigate based on your suggestions and if I find the answer I will respond again.

Ryoma Han

unread,
Feb 29, 2024, 4:08:20 PMFeb 29
to Django developers (Contributions to Django itself)
I've found the reason why I've been thinking this wrong way. 

`getattr(self.get_queryset(), name)` is getting a bound method from Manager.get_queryset() which is a QuerySet class instance, while method is getting function from _queryset_class.

The difference is one of them is bound method, while the other is function.

在2024年2月28日星期三 UTC+8 10:13:09<Tim Graham> 写道:
Reply all
Reply to author
Forward
0 new messages