{"action":"created","comment":{"url":"https://api.github.com/repos/django/django/pulls/comments/166319386","pull_request_review_id":94362170,"id":166319386,"diff_hunk":"@@ -1099,3 +1105,108 @@ def test_list_filter_queryset_filtered_by_default(self):\n         changelist = modeladmin.get_changelist_instance(request)\n         changelist.get_results(request)\n         self.assertEqual(changelist.full_result_count, 4)\n+\n+    def test_should_filter_by_date_hierarchy(self):\n+        modeladmin = BookAdminWithDateHierarchy(Book, site)\n+\n+        def _test_date_hierarchy(query, expected_from_date, expected_to_date):","path":"tests/admin_filters/tests.py","position":32,"original_position":32,"commit_id":"4e55f98c2bf3adf4bdcafa248349abe9f8ef5298","original_commit_id":"4e55f98c2bf3adf4bdcafa248349abe9f8ef5298","user":{"login":"hakib","id":6884290,"avatar_url":"https://avatars3.githubusercontent.com/u/6884290?v=4","gravatar_id":"","url":"https://api.github.com/users/hakib","html_url":"https://github.com/hakib","followers_url":"https://api.github.com/users/hakib/followers","following_url":"https://api.github.com/users/hakib/following{/other_user}","gists_url":"https://api.github.com/users/hakib/gists{/gist_id}","starred_url":"https://api.github.com/users/hakib/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hakib/subscriptions","organizations_url":"https://api.github.com/users/hakib/orgs","repos_url":"https://api.github.com/users/hakib/repos","events_url":"https://api.github.com/users/hakib/events{/privacy}","received_events_url":"https://api.github.com/users/hakib/received_events","type":"User","site_admin":false},"body":"I followed the convntion used [a few tests up](https://github.com/hakib/django/blob/4e55f98c2bf3adf4bdcafa248349abe9f8ef5298/tests/admin_filters/tests.py#L1082). \r\n\r\nI also think a name like `assertDateHierarchy` might imply it's avaliable as part of `TestCase` (such as other Django asserts like `assertNumQueries`).","created_at":"2018-02-06T14:30:34Z","updated_at":"2018-02-06T14:30:35Z","html_url":"https://github.com/django/django/pull/9469#discussion_r166319386","pull_request_url":"https://api.github.com/repos/django/django/pulls/9469","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/django/django/pulls/comments/166319386"},"html":{"href":"https://github.com/django/django/pull/9469#discussion_r166319386"},"pull_request":{"href":"https://api.github.com/repos/django/django/pulls/9469"}},"in_reply_to_id":166310267},"pull_request":{"url":"https://api.github.com/repos/django/django/pulls/9469","id":158744635,"html_url":"https://github.com/django/django/pull/9469","diff_url":"https://github.com/django/django/pull/9469.diff","patch_url":"https://github.com/django/django/pull/9469.patch","issue_url":"https://api.github.com/repos/django/django/issues/9469","number":9469,"state":"open","locked":false,"title":"Fixed #28933 -- Custom range-based filter for date_hierarchy","user":{"login":"hakib","id":6884290,"avatar_url":"https://avatars3.githubusercontent.com/u/6884290?v=4","gravatar_id":"","url":"https://api.github.com/users/hakib","html_url":"https://github.com/hakib","followers_url":"https://api.github.com/users/hakib/followers","following_url":"https://api.github.com/users/hakib/following{/other_user}","gists_url":"https://api.github.com/users/hakib/gists{/gist_id}","starred_url":"https://api.github.com/users/hakib/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hakib/subscriptions","organizations_url":"https://api.github.com/users/hakib/orgs","repos_url":"https://api.github.com/users/hakib/repos","events_url":"https://api.github.com/users/hakib/events{/privacy}","received_events_url":"https://api.github.com/users/hakib/received_events","type":"User","site_admin":false},"body":"[Ticket](https://code.djangoproject.com/ticket/28933#ticket)\r\n\r\nThe predicate generated by date_hierarchy makes it very difficult for databases to optimize the query.\r\n\r\nThe following date hierarchy:\r\n```\r\n/admin/app/model?created__year=2017&created__month=12&created__day=16\r\n```\r\n\r\nWill generate the following where clause (PostgreSql):\r\n```\r\nWHERE created between '2017-01-01' and '2017-31-12' and EXTRACT('month', created) = 12 and EXTRACT('day', created) = 16\r\n```\r\n\r\nThe query above will not be able to utilize range based indexes on the date hierarchy column - on big tables this has a significant performance impact.\r\n\r\nThe current implementation of date hierarchy is relying on the \"default\" filtering mechinizem used by Django Admin. **I propose implementing custom filtering for Django Admin that will better utilize it's hierarchical nature and make it more database \"friendly\".**\r\n\r\nInstead of the query above the date hierarchy would generate the following predicates for different levels of the heirarchy:\r\n```\r\n/admin/app/model?created__year=2017&created__month=12&created__day=16 \r\nWHERE created >= '2017-12-16' and created < '2017-12-17'\r\n```\r\n```\r\n/admin/app/model?created__year=2017&created__month=12\r\nWHERE created >= '2017-12-01' and created < '2018-01-01'\r\n```\r\n```\r\n/admin/app/model?created__year=2017\r\nWHERE created >= '2017-01-01' and created < '2018-01-01'\r\n```\r\n\r\nPlease let me know if this is acceptable.","created_at":"2017-12-16T13:31:54Z","updated_at":"2018-02-06T14:30:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d7f4da47e0998ab0d5263ed3f8223fa39697a799","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"milestone":null,"commits_url":"https://api.github.com/repos/django/django/pulls/9469/commits","review_comments_url":"https://api.github.com/repos/django/django/pulls/9469/comments","review_comment_url":"https://api.github.com/repos/django/django/pulls/comments{/number}","comments_url":"https://api.github.com/repos/django/django/issues/9469/comments","statuses_url":"https://api.github.com/repos/django/django/statuses/4e55f98c2bf3adf4bdcafa248349abe9f8ef5298","head":{"label":"hakib:ticket_28933","ref":"ticket_28933","sha":"4e55f98c2bf3adf4bdcafa248349abe9f8ef5298","user":{"login":"hakib","id":6884290,"avatar_url":"https://avatars3.githubusercontent.com/u/6884290?v=4","gravatar_id":"","url":"https://api.github.com/users/hakib","html_url":"https://github.com/hakib","followers_url":"https://api.github.com/users/hakib/followers","following_url":"https://api.github.com/users/hakib/following{/other_user}","gists_url":"https://api.github.com/users/hakib/gists{/gist_id}","starred_url":"https://api.github.com/users/hakib/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hakib/subscriptions","organizations_url":"https://api.github.com/users/hakib/orgs","repos_url":"https://api.github.com/users/hakib/repos","events_url":"https://api.github.com/users/hakib/events{/privacy}","received_events_url":"https://api.github.com/users/hakib/received_events","type":"User","site_admin":false},"repo":{"id":114462756,"name":"django","full_name":"hakib/django","owner":{"login":"hakib","id":6884290,"avatar_url":"https://avatars3.githubusercontent.com/u/6884290?v=4","gravatar_id":"","url":"https://api.github.com/users/hakib","html_url":"https://github.com/hakib","followers_url":"https://api.github.com/users/hakib/followers","following_url":"https://api.github.com/users/hakib/following{/other_user}","gists_url":"https://api.github.com/users/hakib/gists{/gist_id}","starred_url":"https://api.github.com/users/hakib/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hakib/subscriptions","organizations_url":"https://api.github.com/users/hakib/orgs","repos_url":"https://api.github.com/users/hakib/repos","events_url":"https://api.github.com/users/hakib/events{/privacy}","received_events_url":"https://api.github.com/users/hakib/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/hakib/django","description":"The Web framework for perfectionists with deadlines.","fork":true,"url":"https://api.github.com/repos/hakib/django","forks_url":"https://api.github.com/repos/hakib/django/forks","keys_url":"https://api.github.com/repos/hakib/django/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hakib/django/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hakib/django/teams","hooks_url":"https://api.github.com/repos/hakib/django/hooks","issue_events_url":"https://api.github.com/repos/hakib/django/issues/events{/number}","events_url":"https://api.github.com/repos/hakib/django/events","assignees_url":"https://api.github.com/repos/hakib/django/assignees{/user}","branches_url":"https://api.github.com/repos/hakib/django/branches{/branch}","tags_url":"https://api.github.com/repos/hakib/django/tags","blobs_url":"https://api.github.com/repos/hakib/django/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hakib/django/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hakib/django/git/refs{/sha}","trees_url":"https://api.github.com/repos/hakib/django/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hakib/django/statuses/{sha}","languages_url":"https://api.github.com/repos/hakib/django/languages","stargazers_url":"https://api.github.com/repos/hakib/django/stargazers","contributors_url":"https://api.github.com/repos/hakib/django/contributors","subscribers_url":"https://api.github.com/repos/hakib/django/subscribers","subscription_url":"https://api.github.com/repos/hakib/django/subscription","commits_url":"https://api.github.com/repos/hakib/django/commits{/sha}","git_commits_url":"https://api.github.com/repos/hakib/django/git/commits{/sha}","comments_url":"https://api.github.com/repos/hakib/django/comments{/number}","issue_comment_url":"https://api.github.com/repos/hakib/django/issues/comments{/number}","contents_url":"https://api.github.com/repos/hakib/django/contents/{+path}","compare_url":"https://api.github.com/repos/hakib/django/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hakib/django/merges","archive_url":"https://api.github.com/repos/hakib/django/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hakib/django/downloads","issues_url":"https://api.github.com/repos/hakib/django/issues{/number}","pulls_url":"https://api.github.com/repos/hakib/django/pulls{/number}","milestones_url":"https://api.github.com/repos/hakib/django/milestones{/number}","notifications_url":"https://api.github.com/repos/hakib/django/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hakib/django/labels{/name}","releases_url":"https://api.github.com/repos/hakib/django/releases{/id}","deployments_url":"https://api.github.com/repos/hakib/django/deployments","created_at":"2017-12-16T13:25:56Z","updated_at":"2017-12-16T13:26:15Z","pushed_at":"2017-12-16T18:54:14Z","git_url":"git://github.com/hakib/django.git","ssh_url":"git@github.com:hakib/django.git","clone_url":"https://github.com/hakib/django.git","svn_url":"https://github.com/hakib/django","homepage":"https://www.djangoproject.com/","size":173212,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"django:master","ref":"master","sha":"6fd6d8383f48ea2fe4e058725fa30529a083e9a5","user":{"login":"django","id":27804,"avatar_url":"https://avatars2.githubusercontent.com/u/27804?v=4","gravatar_id":"","url":"https://api.github.com/users/django","html_url":"https://github.com/django","followers_url":"https://api.github.com/users/django/followers","following_url":"https://api.github.com/users/django/following{/other_user}","gists_url":"https://api.github.com/users/django/gists{/gist_id}","starred_url":"https://api.github.com/users/django/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/django/subscriptions","organizations_url":"https://api.github.com/users/django/orgs","repos_url":"https://api.github.com/users/django/repos","events_url":"https://api.github.com/users/django/events{/privacy}","received_events_url":"https://api.github.com/users/django/received_events","type":"Organization","site_admin":false},"repo":{"id":4164482,"name":"django","full_name":"django/django","owner":{"login":"django","id":27804,"avatar_url":"https://avatars2.githubusercontent.com/u/27804?v=4","gravatar_id":"","url":"https://api.github.com/users/django","html_url":"https://github.com/django","followers_url":"https://api.github.com/users/django/followers","following_url":"https://api.github.com/users/django/following{/other_user}","gists_url":"https://api.github.com/users/django/gists{/gist_id}","starred_url":"https://api.github.com/users/django/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/django/subscriptions","organizations_url":"https://api.github.com/users/django/orgs","repos_url":"https://api.github.com/users/django/repos","events_url":"https://api.github.com/users/django/events{/privacy}","received_events_url":"https://api.github.com/users/django/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/django/django","description":"The Web framework for perfectionists with deadlines.","fork":false,"url":"https://api.github.com/repos/django/django","forks_url":"https://api.github.com/repos/django/django/forks","keys_url":"https://api.github.com/repos/django/django/keys{/key_id}","collaborators_url":"https://api.github.com/repos/django/django/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/django/django/teams","hooks_url":"https://api.github.com/repos/django/django/hooks","issue_events_url":"https://api.github.com/repos/django/django/issues/events{/number}","events_url":"https://api.github.com/repos/django/django/events","assignees_url":"https://api.github.com/repos/django/django/assignees{/user}","branches_url":"https://api.github.com/repos/django/django/branches{/branch}","tags_url":"https://api.github.com/repos/django/django/tags","blobs_url":"https://api.github.com/repos/django/django/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/django/django/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/django/django/git/refs{/sha}","trees_url":"https://api.github.com/repos/django/django/git/trees{/sha}","statuses_url":"https://api.github.com/repos/django/django/statuses/{sha}","languages_url":"https://api.github.com/repos/django/django/languages","stargazers_url":"https://api.github.com/repos/django/django/stargazers","contributors_url":"https://api.github.com/repos/django/django/contributors","subscribers_url":"https://api.github.com/repos/django/django/subscribers","subscription_url":"https://api.github.com/repos/django/django/subscription","commits_url":"https://api.github.com/repos/django/django/commits{/sha}","git_commits_url":"https://api.github.com/repos/django/django/git/commits{/sha}","comments_url":"https://api.github.com/repos/django/django/comments{/number}","issue_comment_url":"https://api.github.com/repos/django/django/issues/comments{/number}","contents_url":"https://api.github.com/repos/django/django/contents/{+path}","compare_url":"https://api.github.com/repos/django/django/compare/{base}...{head}","merges_url":"https://api.github.com/repos/django/django/merges","archive_url":"https://api.github.com/repos/django/django/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/django/django/downloads","issues_url":"https://api.github.com/repos/django/django/issues{/number}","pulls_url":"https://api.github.com/repos/django/django/pulls{/number}","milestones_url":"https://api.github.com/repos/django/django/milestones{/number}","notifications_url":"https://api.github.com/repos/django/django/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/django/django/labels{/name}","releases_url":"https://api.github.com/repos/django/django/releases{/id}","deployments_url":"https://api.github.com/repos/django/django/deployments","created_at":"2012-04-28T02:47:18Z","updated_at":"2018-02-06T14:15:24Z","pushed_at":"2018-02-06T14:23:38Z","git_url":"git://github.com/django/django.git","ssh_url":"git@github.com:django/django.git","clone_url":"https://github.com/django/django.git","svn_url":"https://github.com/django/django","homepage":"https://www.djangoproject.com/","size":174296,"stargazers_count":31560,"watchers_count":31560,"language":"Python","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":13349,"mirror_url":null,"archived":false,"open_issues_count":204,"license":null,"forks":13349,"open_issues":204,"watchers":31560,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/django/django/pulls/9469"},"html":{"href":"https://github.com/django/django/pull/9469"},"issue":{"href":"https://api.github.com/repos/django/django/issues/9469"},"comments":{"href":"https://api.github.com/repos/django/django/issues/9469/comments"},"review_comments":{"href":"https://api.github.com/repos/django/django/pulls/9469/comments"},"review_comment":{"href":"https://api.github.com/repos/django/django/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/django/django/pulls/9469/commits"},"statuses":{"href":"https://api.github.com/repos/django/django/statuses/4e55f98c2bf3adf4bdcafa248349abe9f8ef5298"}},"author_association":"NONE"}}
{"actor":{"display_login":"hakib"}}