{"action":"created","comment":{"url":"https://api.github.com/repos/divio/django-cms/pulls/comments/57537490","id":57537490,"diff_hunk":"@@ -4,6 +4,7 @@\n * Set the default value of CMSPlugin.position to 0 instead of null\n * Refactor language menu to allow for better integration with many languages\n * Management commands has been completely refactored for better consistency\n+* Provides the ability to declare expiration periods on a per-plugin basis","path":"CHANGELOG.txt","position":4,"original_position":4,"commit_id":"dd4e32000e9f03f9343ab1fcebf533657067bce3","original_commit_id":"dd4e32000e9f03f9343ab1fcebf533657067bce3","user":{"login":"czpython","id":994951,"avatar_url":"https://avatars.githubusercontent.com/u/994951?v=3","gravatar_id":"","url":"https://api.github.com/users/czpython","html_url":"https://github.com/czpython","followers_url":"https://api.github.com/users/czpython/followers","following_url":"https://api.github.com/users/czpython/following{/other_user}","gists_url":"https://api.github.com/users/czpython/gists{/gist_id}","starred_url":"https://api.github.com/users/czpython/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/czpython/subscriptions","organizations_url":"https://api.github.com/users/czpython/orgs","repos_url":"https://api.github.com/users/czpython/repos","events_url":"https://api.github.com/users/czpython/events{/privacy}","received_events_url":"https://api.github.com/users/czpython/received_events","type":"User","site_admin":false},"body":"to declare **cache** expiration periods","created_at":"2016-03-28T00:34:24Z","updated_at":"2016-03-28T00:34:24Z","html_url":"https://github.com/divio/django-cms/pull/5095#discussion_r57537490","pull_request_url":"https://api.github.com/repos/divio/django-cms/pulls/5095","_links":{"self":{"href":"https://api.github.com/repos/divio/django-cms/pulls/comments/57537490"},"html":{"href":"https://github.com/divio/django-cms/pull/5095#discussion_r57537490"},"pull_request":{"href":"https://api.github.com/repos/divio/django-cms/pulls/5095"}}},"pull_request":{"url":"https://api.github.com/repos/divio/django-cms/pulls/5095","id":63570324,"html_url":"https://github.com/divio/django-cms/pull/5095","diff_url":"https://github.com/divio/django-cms/pull/5095.diff","patch_url":"https://github.com/divio/django-cms/pull/5095.patch","issue_url":"https://api.github.com/repos/divio/django-cms/issues/5095","number":5095,"state":"open","locked":false,"title":"Better cache control","user":{"login":"mkoistinen","id":615759,"avatar_url":"https://avatars.githubusercontent.com/u/615759?v=3","gravatar_id":"","url":"https://api.github.com/users/mkoistinen","html_url":"https://github.com/mkoistinen","followers_url":"https://api.github.com/users/mkoistinen/followers","following_url":"https://api.github.com/users/mkoistinen/following{/other_user}","gists_url":"https://api.github.com/users/mkoistinen/gists{/gist_id}","starred_url":"https://api.github.com/users/mkoistinen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mkoistinen/subscriptions","organizations_url":"https://api.github.com/users/mkoistinen/orgs","repos_url":"https://api.github.com/users/mkoistinen/repos","events_url":"https://api.github.com/users/mkoistinen/events{/privacy}","received_events_url":"https://api.github.com/users/mkoistinen/received_events","type":"User","site_admin":false},"body":"In earlier versions of the CMS a plugin author had only one mechanism to affect the cache-ability of the rendered output: setting the CMSPluginBase attribute `cache` to False. The result of this would be that any placeholder, and thus page that contained the plugin would emit the HTTP header `Cache-Control: no-cache, max-age=0, must-revalidate, no-store`.\r\n\r\nWhile this was useful, it is essentially the \"nuclear option\"; only really useful when the plugin is delivering unique content for every request. In any other scenario, this is overkill and simply degrades the performance of the resulting site.\r\n\r\nA useful scenario to imagine is a CalendarPlugin which always displays the current month. In earlier versions of the CMS, in order to achieve this, the plugin would have to set `cache = False` rendering the entire page never cached, just so that it would be updated once a month.\r\n\r\nIn order to address this sort of use-case, this PR augments the CMSPluginBase with a default method `get_cache_expiration(request, instance)` which, by default, returns `None`. The CalendarPlugin developer, (for example) however, can override this to return the last second of the current month as a (timezone-aware) `datetime` instance. This tells the CMS' caching sub-system that any page containing this plugin is cache-able––at most––until the last second of the current month.\r\n\r\nIf the `CMS_CACHES['content']` setting is greater than the time remaining until the end of the month and there are no other plugins, then indeed, the page will expire at the end of the month.\r\n\r\nThe `get_cache_expiration()` may also return a `datetime.timedelta` instance or just an integer number of seconds, which will serve the same purpose, but in a manner relative to the response time of the page.\r\n\r\nAs `get_cache_expiration()` is a method, with access to `instance` (the CMSPlugin instance), a full range of options are available to the plugin developer, allowing expiration that is determined at runtime, if required.","created_at":"2016-03-21T14:18:03Z","updated_at":"2016-03-28T00:34:24Z","closed_at":null,"merged_at":null,"merge_commit_sha":"87e6cd8c638ab56d4b50289fddd7142094981910","assignee":null,"milestone":{"url":"https://api.github.com/repos/divio/django-cms/milestones/40","html_url":"https://github.com/divio/django-cms/milestones/3.3","labels_url":"https://api.github.com/repos/divio/django-cms/milestones/40/labels","id":1333248,"number":40,"title":"3.3","description":"Rethinking menus and improving the UX of the pagetree.","creator":{"login":"mkoistinen","id":615759,"avatar_url":"https://avatars.githubusercontent.com/u/615759?v=3","gravatar_id":"","url":"https://api.github.com/users/mkoistinen","html_url":"https://github.com/mkoistinen","followers_url":"https://api.github.com/users/mkoistinen/followers","following_url":"https://api.github.com/users/mkoistinen/following{/other_user}","gists_url":"https://api.github.com/users/mkoistinen/gists{/gist_id}","starred_url":"https://api.github.com/users/mkoistinen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mkoistinen/subscriptions","organizations_url":"https://api.github.com/users/mkoistinen/orgs","repos_url":"https://api.github.com/users/mkoistinen/repos","events_url":"https://api.github.com/users/mkoistinen/events{/privacy}","received_events_url":"https://api.github.com/users/mkoistinen/received_events","type":"User","site_admin":false},"open_issues":34,"closed_issues":42,"state":"open","created_at":"2015-10-01T14:26:39Z","updated_at":"2016-03-24T16:52:28Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/divio/django-cms/pulls/5095/commits","review_comments_url":"https://api.github.com/repos/divio/django-cms/pulls/5095/comments","review_comment_url":"https://api.github.com/repos/divio/django-cms/pulls/comments{/number}","comments_url":"https://api.github.com/repos/divio/django-cms/issues/5095/comments","statuses_url":"https://api.github.com/repos/divio/django-cms/statuses/dd4e32000e9f03f9343ab1fcebf533657067bce3","head":{"label":"mkoistinen:feature/better_cache_control","ref":"feature/better_cache_control","sha":"dd4e32000e9f03f9343ab1fcebf533657067bce3","user":{"login":"mkoistinen","id":615759,"avatar_url":"https://avatars.githubusercontent.com/u/615759?v=3","gravatar_id":"","url":"https://api.github.com/users/mkoistinen","html_url":"https://github.com/mkoistinen","followers_url":"https://api.github.com/users/mkoistinen/followers","following_url":"https://api.github.com/users/mkoistinen/following{/other_user}","gists_url":"https://api.github.com/users/mkoistinen/gists{/gist_id}","starred_url":"https://api.github.com/users/mkoistinen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mkoistinen/subscriptions","organizations_url":"https://api.github.com/users/mkoistinen/orgs","repos_url":"https://api.github.com/users/mkoistinen/repos","events_url":"https://api.github.com/users/mkoistinen/events{/privacy}","received_events_url":"https://api.github.com/users/mkoistinen/received_events","type":"User","site_admin":false},"repo":{"id":16410287,"name":"django-cms","full_name":"mkoistinen/django-cms","owner":{"login":"mkoistinen","id":615759,"avatar_url":"https://avatars.githubusercontent.com/u/615759?v=3","gravatar_id":"","url":"https://api.github.com/users/mkoistinen","html_url":"https://github.com/mkoistinen","followers_url":"https://api.github.com/users/mkoistinen/followers","following_url":"https://api.github.com/users/mkoistinen/following{/other_user}","gists_url":"https://api.github.com/users/mkoistinen/gists{/gist_id}","starred_url":"https://api.github.com/users/mkoistinen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mkoistinen/subscriptions","organizations_url":"https://api.github.com/users/mkoistinen/orgs","repos_url":"https://api.github.com/users/mkoistinen/repos","events_url":"https://api.github.com/users/mkoistinen/events{/privacy}","received_events_url":"https://api.github.com/users/mkoistinen/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mkoistinen/django-cms","description":"The easy-to-use and developer-friendly CMS","fork":true,"url":"https://api.github.com/repos/mkoistinen/django-cms","forks_url":"https://api.github.com/repos/mkoistinen/django-cms/forks","keys_url":"https://api.github.com/repos/mkoistinen/django-cms/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mkoistinen/django-cms/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mkoistinen/django-cms/teams","hooks_url":"https://api.github.com/repos/mkoistinen/django-cms/hooks","issue_events_url":"https://api.github.com/repos/mkoistinen/django-cms/issues/events{/number}","events_url":"https://api.github.com/repos/mkoistinen/django-cms/events","assignees_url":"https://api.github.com/repos/mkoistinen/django-cms/assignees{/user}","branches_url":"https://api.github.com/repos/mkoistinen/django-cms/branches{/branch}","tags_url":"https://api.github.com/repos/mkoistinen/django-cms/tags","blobs_url":"https://api.github.com/repos/mkoistinen/django-cms/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mkoistinen/django-cms/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mkoistinen/django-cms/git/refs{/sha}","trees_url":"https://api.github.com/repos/mkoistinen/django-cms/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mkoistinen/django-cms/statuses/{sha}","languages_url":"https://api.github.com/repos/mkoistinen/django-cms/languages","stargazers_url":"https://api.github.com/repos/mkoistinen/django-cms/stargazers","contributors_url":"https://api.github.com/repos/mkoistinen/django-cms/contributors","subscribers_url":"https://api.github.com/repos/mkoistinen/django-cms/subscribers","subscription_url":"https://api.github.com/repos/mkoistinen/django-cms/subscription","commits_url":"https://api.github.com/repos/mkoistinen/django-cms/commits{/sha}","git_commits_url":"https://api.github.com/repos/mkoistinen/django-cms/git/commits{/sha}","comments_url":"https://api.github.com/repos/mkoistinen/django-cms/comments{/number}","issue_comment_url":"https://api.github.com/repos/mkoistinen/django-cms/issues/comments{/number}","contents_url":"https://api.github.com/repos/mkoistinen/django-cms/contents/{+path}","compare_url":"https://api.github.com/repos/mkoistinen/django-cms/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mkoistinen/django-cms/merges","archive_url":"https://api.github.com/repos/mkoistinen/django-cms/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mkoistinen/django-cms/downloads","issues_url":"https://api.github.com/repos/mkoistinen/django-cms/issues{/number}","pulls_url":"https://api.github.com/repos/mkoistinen/django-cms/pulls{/number}","milestones_url":"https://api.github.com/repos/mkoistinen/django-cms/milestones{/number}","notifications_url":"https://api.github.com/repos/mkoistinen/django-cms/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mkoistinen/django-cms/labels{/name}","releases_url":"https://api.github.com/repos/mkoistinen/django-cms/releases{/id}","deployments_url":"https://api.github.com/repos/mkoistinen/django-cms/deployments","created_at":"2014-01-31T14:35:19Z","updated_at":"2015-03-04T16:30:48Z","pushed_at":"2016-03-23T12:48:53Z","git_url":"git://github.com/mkoistinen/django-cms.git","ssh_url":"git@github.com:mkoistinen/django-cms.git","clone_url":"https://github.com/mkoistinen/django-cms.git","svn_url":"https://github.com/mkoistinen/django-cms","homepage":"http://www.django-cms.org","size":59525,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"divio:develop","ref":"develop","sha":"d04f1e24a011368c19ac4b0e60936dc1800f362d","user":{"login":"divio","id":117904,"avatar_url":"https://avatars.githubusercontent.com/u/117904?v=3","gravatar_id":"","url":"https://api.github.com/users/divio","html_url":"https://github.com/divio","followers_url":"https://api.github.com/users/divio/followers","following_url":"https://api.github.com/users/divio/following{/other_user}","gists_url":"https://api.github.com/users/divio/gists{/gist_id}","starred_url":"https://api.github.com/users/divio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/divio/subscriptions","organizations_url":"https://api.github.com/users/divio/orgs","repos_url":"https://api.github.com/users/divio/repos","events_url":"https://api.github.com/users/divio/events{/privacy}","received_events_url":"https://api.github.com/users/divio/received_events","type":"Organization","site_admin":false},"repo":{"id":143580,"name":"django-cms","full_name":"divio/django-cms","owner":{"login":"divio","id":117904,"avatar_url":"https://avatars.githubusercontent.com/u/117904?v=3","gravatar_id":"","url":"https://api.github.com/users/divio","html_url":"https://github.com/divio","followers_url":"https://api.github.com/users/divio/followers","following_url":"https://api.github.com/users/divio/following{/other_user}","gists_url":"https://api.github.com/users/divio/gists{/gist_id}","starred_url":"https://api.github.com/users/divio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/divio/subscriptions","organizations_url":"https://api.github.com/users/divio/orgs","repos_url":"https://api.github.com/users/divio/repos","events_url":"https://api.github.com/users/divio/events{/privacy}","received_events_url":"https://api.github.com/users/divio/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/divio/django-cms","description":"The easy-to-use and developer-friendly CMS","fork":false,"url":"https://api.github.com/repos/divio/django-cms","forks_url":"https://api.github.com/repos/divio/django-cms/forks","keys_url":"https://api.github.com/repos/divio/django-cms/keys{/key_id}","collaborators_url":"https://api.github.com/repos/divio/django-cms/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/divio/django-cms/teams","hooks_url":"https://api.github.com/repos/divio/django-cms/hooks","issue_events_url":"https://api.github.com/repos/divio/django-cms/issues/events{/number}","events_url":"https://api.github.com/repos/divio/django-cms/events","assignees_url":"https://api.github.com/repos/divio/django-cms/assignees{/user}","branches_url":"https://api.github.com/repos/divio/django-cms/branches{/branch}","tags_url":"https://api.github.com/repos/divio/django-cms/tags","blobs_url":"https://api.github.com/repos/divio/django-cms/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/divio/django-cms/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/divio/django-cms/git/refs{/sha}","trees_url":"https://api.github.com/repos/divio/django-cms/git/trees{/sha}","statuses_url":"https://api.github.com/repos/divio/django-cms/statuses/{sha}","languages_url":"https://api.github.com/repos/divio/django-cms/languages","stargazers_url":"https://api.github.com/repos/divio/django-cms/stargazers","contributors_url":"https://api.github.com/repos/divio/django-cms/contributors","subscribers_url":"https://api.github.com/repos/divio/django-cms/subscribers","subscription_url":"https://api.github.com/repos/divio/django-cms/subscription","commits_url":"https://api.github.com/repos/divio/django-cms/commits{/sha}","git_commits_url":"https://api.github.com/repos/divio/django-cms/git/commits{/sha}","comments_url":"https://api.github.com/repos/divio/django-cms/comments{/number}","issue_comment_url":"https://api.github.com/repos/divio/django-cms/issues/comments{/number}","contents_url":"https://api.github.com/repos/divio/django-cms/contents/{+path}","compare_url":"https://api.github.com/repos/divio/django-cms/compare/{base}...{head}","merges_url":"https://api.github.com/repos/divio/django-cms/merges","archive_url":"https://api.github.com/repos/divio/django-cms/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/divio/django-cms/downloads","issues_url":"https://api.github.com/repos/divio/django-cms/issues{/number}","pulls_url":"https://api.github.com/repos/divio/django-cms/pulls{/number}","milestones_url":"https://api.github.com/repos/divio/django-cms/milestones{/number}","notifications_url":"https://api.github.com/repos/divio/django-cms/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/divio/django-cms/labels{/name}","releases_url":"https://api.github.com/repos/divio/django-cms/releases{/id}","deployments_url":"https://api.github.com/repos/divio/django-cms/deployments","created_at":"2009-03-05T10:14:18Z","updated_at":"2016-03-27T23:21:07Z","pushed_at":"2016-03-26T10:45:48Z","git_url":"git://github.com/divio/django-cms.git","ssh_url":"git@github.com:divio/django-cms.git","clone_url":"https://github.com/divio/django-cms.git","svn_url":"https://github.com/divio/django-cms","homepage":"http://www.django-cms.org","size":87826,"stargazers_count":4064,"watchers_count":4064,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1540,"mirror_url":null,"open_issues_count":244,"forks":1540,"open_issues":244,"watchers":4064,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/divio/django-cms/pulls/5095"},"html":{"href":"https://github.com/divio/django-cms/pull/5095"},"issue":{"href":"https://api.github.com/repos/divio/django-cms/issues/5095"},"comments":{"href":"https://api.github.com/repos/divio/django-cms/issues/5095/comments"},"review_comments":{"href":"https://api.github.com/repos/divio/django-cms/pulls/5095/comments"},"review_comment":{"href":"https://api.github.com/repos/divio/django-cms/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/divio/django-cms/pulls/5095/commits"},"statuses":{"href":"https://api.github.com/repos/divio/django-cms/statuses/dd4e32000e9f03f9343ab1fcebf533657067bce3"}}}}