django icon indicating copy to clipboard operation
django copied to clipboard

WIP #29799 -- Per-Field-instance lookups

Open AllenJonathan opened this issue 1 year ago β€’ 15 comments

AllenJonathan avatar Jun 23 '22 06:06 AllenJonathan

This class seems to be the best way to differentiate class or instance calls (though a little less readable). I am unclear about whether tests should be written for this class separately (since this would be tested indirectly when other methods are tested).

AllenJonathan avatar Jun 23 '22 07:06 AllenJonathan

@AllenJonathan Thanks :+1: I don't think it's worth adding only classorinstancemethod. It's difficult to judge how useful it is without remaining elements. Can you add other pieces (even a draft) that we could discuss the implementation details?

felixxm avatar Jul 08 '22 06:07 felixxm

Please ignore the linter errors (using a different device and so facing issues with pre-commit). register_lookup and _unregister_lookup seems to working as it should be.

One issue that I'm facing is that all Field instances are wrapped in DeferredAttribute class. Which make the syntax like this: Model.name.field.register_lookup(Lookup) instead of: Model.name.register_lookup(Lookup).

AllenJonathan avatar Jul 12 '22 08:07 AllenJonathan

Please ignore the linter errors (using a different device and so facing issues with pre-commit).

You don't need to use pre-commit, you can call black and isort on changed files.

felixxm avatar Jul 15 '22 03:07 felixxm

@AllenJonathan Thanks πŸ‘ This PR is mainly based on charettes@ccc58bf. We need much more: new context processors for registering lookups per field/instance, support reverse relations, tests with all three layers (class, instance, field) etc.

Any related pull request could be helpful. Also, I don't understand how context processors would come into play here, As far as I know, context_processors are used to render data in templates.

AllenJonathan avatar Jul 18 '22 18:07 AllenJonathan

Also, I don't understand how context processors would come into play here, As far as I know, context_processors are used to render data in templates.

Context processors have many uses, I'm thinking about sth similar to the django.test.utils.register_lookup: https://github.com/django/django/blob/e59d1ff5627cf9cc551e160d65858a37693de4ed/django/test/utils.py#L989-L1001

felixxm avatar Jul 18 '22 18:07 felixxm

Also, I don't understand how context processors would come into play here, As far as I know, context_processors are used to render data in templates.

Context processors have many uses, I'm thinking about sth similar to the django.test.utils.register_lookup:

https://github.com/django/django/blob/e59d1ff5627cf9cc551e160d65858a37693de4ed/django/test/utils.py#L989-L1001

So as far as I understand, a context processor that would temporarily register (Field/instance) lookup should be added. In this way, testing would be simplified as the lookups would be unregistered automatically. So the use case would be for testing only. Am I right?

AllenJonathan avatar Jul 19 '22 07:07 AllenJonathan

So as far as I understand, a context processor that would temporarily register (Field/instance) lookup should be added. In this way, testing would be simplified as the lookups would be unregistered automatically. So the use case would be for testing only. Am I right?

Yes.

felixxm avatar Jul 19 '22 07:07 felixxm

  1. Tests are written for both Field class and instances. The basic filter tests seem to work. Let me know about other corner cases that can added.

One issue that I'm facing is that all Field instances are wrapped in DeferredAttribute class. Which make the syntax like this: Model.name.field.register_lookup(Lookup) instead of: Model.name.register_lookup(Lookup).

  1. This could be solved easily by adding the necessary functions in DeferredAttribute as class variables (functions). But I'm unsure whether to do so. Or we could also make the syntax as Model.name.field.register_lookup(Lookup). Let me know which should be done

  2. Should an error be given if an unregistered lookup is unregistered. If yes what error could it be?

  3. About context processors register_lookup present in the django.test.utils. I feel no change needs to be done here. As the register_lookup automatically differentiates class and instances and you can see in the tests that it works perfectly fine. Let me know why exactly a new context processor should be implemented.

I would start now on the documentation changes. Maybe reverse relations could be done after these things are completed and resolved? But some insight into what needs to be done about reverse relations would be very helpful.

AllenJonathan avatar Jul 20 '22 11:07 AllenJonathan

@felixxm I've made some changes. Please look into it. Let me know if there is anything else to add(or change) here. I'm going to start adding documentation changes.

AllenJonathan avatar Jul 23 '22 03:07 AllenJonathan

We already got a document pattern of to access model fields so it seems a bit odd to me that we add all of this code to support an uncommon access pattern anyway.

Agreed, let's simplify this :+1:

felixxm avatar Jul 26 '22 05:07 felixxm

Agreed, let's simplify this πŸ‘

Ok. I'll mention the pattern to access model fields in the RegisterLookupMixin docs. I too felt that simplifying the syntax using proxy methods would be too much ugly code in several places,

AllenJonathan avatar Jul 26 '22 16:07 AllenJonathan

I was wondering what are the benefits of performing any queries in RegisterLookupTests.

Couldn't we simply use get_lookup to assert the registration works fine instead of hitting the database? It seems it would also make the tests more explicit.

This could be done and it would be fine. I've been hitting the database to ensure all the code works from the user level. I think there's no harm in testing by just using get_lookup either. But do let me know what to do.

AllenJonathan avatar Jul 26 '22 17:07 AllenJonathan

For what it's worth I'm not entirely convinced that adding the Model.field.register_lookup sugar is actually worth all the boilerplate it requires.

We already got a document pattern of to access model fields so it seems a bit odd to me that we add all of this code to support an uncommon access pattern anyway.

Just my 2 cents.

DoneπŸ‘

AllenJonathan avatar Jul 26 '22 18:07 AllenJonathan

Couldn't we simply use get_lookup to assert the registration works fine instead of hitting the database? It seems it would also make the tests more explicit.

Agreed, let's switch to SimpleTestCase and get_lookups() assertions, without actually hitting the database.

felixxm avatar Jul 28 '22 07:07 felixxm

I think this PR is completed. Is it ok to open this PR to merge?

AllenJonathan avatar Aug 12 '22 19:08 AllenJonathan

I have opened up a PR of ticket - 26511 -- Document KeyTransform and KeyTextTransform.

AllenJonathan avatar Aug 12 '22 19:08 AllenJonathan

I think this PR is completed. Is it ok to open this PR to merge?

I will check it next week. Can you explore more and maybe produce djangobench overview (as suggested by Simon)?

"It could be worth exploring as well as producing djangobench overview of the impact of this change on the time spent resolving lookups."

"Does the usage of functools.partial and the extra function call and dict lookup have a significant impact on query creation time?"

felixxm avatar Aug 13 '22 12:08 felixxm

I've run djangobench on my cloned local django repository. I've compared the ticket_29799 branch with the main branch. Here are the results.

qs_filter_chaining, query_aggregate, query_annotate, query_complex_filter, query_exists, and query_values have shown significant difference (slower than before). query_delete, query_filter and query_update have significantly changes (faster than before).

AllenJonathan avatar Aug 19 '22 18:08 AllenJonathan

I used django-asv to compare this branch and the current main branch and there is no significant difference, see results :chart_with_upwards_trend: .

felixxm avatar Sep 01 '22 08:09 felixxm

I squashed commits and rebased after e64919ae54933ef4840f0e27e51d9fcfd55ecf4b.

felixxm avatar Sep 01 '22 08:09 felixxm

@AllenJonathan Thanks :+1:

felixxm avatar Sep 02 '22 08:09 felixxm