Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework ordering filter #1118

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

earshinov
Copy link

See #1021

@earshinov
Copy link
Author

earshinov commented Sep 2, 2019

@carltongibson , @rpkilby , Could you take a look and share your thoughts?

I started with the code and tests.

The updated OrderingFilter maintains full compatibility with the old one. That is, it supports fields, field_labels and choices arguments as before. But it also accepts a new params argument in the form of { param name: ... } that allows to

  • order by several fields
  • order by Django expression(s)
  • apply inverse order (using F(...).desc() as was illustrated in the comment)

TODO:

  • document in docs/ref/filters.txt
  • update docs/guide/migration.txt

@codecov-io
Copy link

codecov-io commented Sep 2, 2019

Codecov Report

Merging #1118 into master will increase coverage by 0.02%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1118      +/-   ##
==========================================
+ Coverage   99.43%   99.45%   +0.02%     
==========================================
  Files          15       15              
  Lines        1235     1296      +61     
==========================================
+ Hits         1228     1289      +61     
  Misses          7        7
Impacted Files Coverage Δ
django_filters/filters.py 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e6d5f2d...edda682. Read the comment docs.

@al-muammar
Copy link

@earshinov, any updates here? I would be happy to use nulls_last feature.

@earshinov
Copy link
Author

@jihadik , Hi! No, I don't have any updates. I think I have pushed everything that I had, now awaiting feedback from django-filter maintainers. The version from this PR should already support nulls_last just fine. I would appreciate if you gave it a try and shared your feedback. It seems that the maintainers are not terribly interested in this feature, and additional user feedback could convince them to pay more attention to it, should they have time.

Copy link

@al-muammar al-muammar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM


self.param_map = {v: k for k, v in fields.items()}
self._params = params

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the code around _params is going against the style. Just use self.params

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, it seems that in the existing code underscores are only utilized to name backing fields used in the implementation of get/set properties. Renamed in edda682.

tests/models.py Outdated
first_name = SubCharField(max_length=100)
last_name = SubSubCharField(max_length=100)
first_name = SubCharField(max_length=100, null=True, blank=True)
last_name = SubSubCharField(max_length=100, null=True, blank=True)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe, by default an empty string is null. Also, you are not using forms, so blank=True is not needed. hence, you don't need to touch these two lines.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe, by default an empty string is null

I am not sure what you mean. null and empty string are different values and are treated differently both by Django ORM and the underlying database.

null=True is necessary because within tests I create some User instances with first_name=null to check handling of nulls. The default value for the null constructor parameter is False.

As for blank=True, maybe User instances are not tied to forms at the moment, but they can be in the future. I think it's a good practice to set blank=True once one defines null=True.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is from the Django official doc: https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.Field.null

As for the blank=True, I believe it should be added on demand. Otherwise, me reading the tests would scratch my head and think why is it necessary to have it here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is from the Django official doc: https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.Field.null

Still, having null=False will prevent us from testing User(first_name=null)

As for the blank=True, I believe it should be added on demand. Otherwise, me reading the tests would scratch my head and think why is it necessary to have it here?

Well, I would rather scratch my head if I saw a field with null=True but blank=False. It clearly won't work with forms at all. I guess we need another opinion here, ideally from django-filter devs.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some experience with Django and would like to share my opinion on this matter. I think having blank=True, null=True on a django CharField is definitely not a best practice and even strongly disencouraged. It means you have two empty values in the database, NULL and '' (empty char). Therefore my recommendation is to rewrite the test by using a datetimeField (for example) with null=True, blank=True. In that case it makes logical sense and the correctness of the test is also faily easily determined.

Having said that I would also love to see this merged! Big applause for @earshinov for undertaking this project!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @gabn88! Sorry that I didn't have time to reply during workdays. Thank you for your input, your suggestion about avoiding nullable/blank CharFields seems very reasonable. I reworked the tests using a DateTime model field instead of CharField and rebased the branch onto the latest master along the way. Hopefully these changes will help merge this PR.

@al-muammar
Copy link

@carltongibson, could I get attention for this PR?
@earshinov, it would be cool if you could merge the latest master, thanks!

@earshinov
Copy link
Author

@jihadik , I rebased the PR on top of the master branch

@codecov-commenter
Copy link

codecov-commenter commented May 24, 2020

Codecov Report

Merging #1118 into master will increase coverage by 0.02%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1118      +/-   ##
==========================================
+ Coverage   99.44%   99.46%   +0.02%     
==========================================
  Files          15       15              
  Lines        1255     1316      +61     
==========================================
+ Hits         1248     1309      +61     
  Misses          7        7              
Impacted Files Coverage Δ
django_filters/filters.py 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 737d75f...e192249. Read the comment docs.

@forgoty
Copy link

forgoty commented May 26, 2020

What is the progress about this task?
@rpkilby

Base automatically changed from master to main March 3, 2021 08:48
@jaap3
Copy link

jaap3 commented Nov 9, 2022

Too bad this has gone stale, I'm in need of a way to have null values sorted to the bottom and had hoped django-filter supported it. Maybe some day...

@axieum
Copy link

axieum commented Nov 17, 2022

I'm also keen to see this across the line 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants