diff --git a/django/contrib/sitemaps/__init__.py b/django/contrib/sitemaps/__init__.py index 5938e34014..dd21d8829d 100644 --- a/django/contrib/sitemaps/__init__.py +++ b/django/contrib/sitemaps/__init__.py @@ -1,60 +1,9 @@ -from urllib.parse import urlencode -from urllib.request import urlopen - from django.apps import apps as django_apps from django.conf import settings from django.core import paginator from django.core.exceptions import ImproperlyConfigured -from django.urls import NoReverseMatch, reverse from django.utils import translation -PING_URL = "https://www.google.com/webmasters/tools/ping" - - -class SitemapNotFound(Exception): - pass - - -def ping_google(sitemap_url=None, ping_url=PING_URL, sitemap_uses_https=True): - """ - Alert Google that the sitemap for the current site has been updated. - If sitemap_url is provided, it should be an absolute path to the sitemap - for this site -- e.g., '/sitemap.xml'. If sitemap_url is not provided, this - function will attempt to deduce it by using urls.reverse(). - """ - sitemap_full_url = _get_sitemap_full_url(sitemap_url, sitemap_uses_https) - params = urlencode({"sitemap": sitemap_full_url}) - urlopen("%s?%s" % (ping_url, params)) - - -def _get_sitemap_full_url(sitemap_url, sitemap_uses_https=True): - if not django_apps.is_installed("django.contrib.sites"): - raise ImproperlyConfigured( - "ping_google requires django.contrib.sites, which isn't installed." - ) - - if sitemap_url is None: - try: - # First, try to get the "index" sitemap URL. - sitemap_url = reverse("django.contrib.sitemaps.views.index") - except NoReverseMatch: - try: - # Next, try for the "global" sitemap URL. - sitemap_url = reverse("django.contrib.sitemaps.views.sitemap") - except NoReverseMatch: - pass - - if sitemap_url is None: - raise SitemapNotFound( - "You didn't provide a sitemap_url, and the sitemap URL couldn't be " - "auto-detected." - ) - - Site = django_apps.get_model("sites.Site") - current_site = Site.objects.get_current() - scheme = "https" if sitemap_uses_https else "http" - return "%s://%s%s" % (scheme, current_site.domain, sitemap_url) - class Sitemap: # This limit is defined by Google. See the index documentation at diff --git a/django/contrib/sitemaps/management/__init__.py b/django/contrib/sitemaps/management/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/django/contrib/sitemaps/management/commands/__init__.py b/django/contrib/sitemaps/management/commands/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/django/contrib/sitemaps/management/commands/ping_google.py b/django/contrib/sitemaps/management/commands/ping_google.py deleted file mode 100644 index 3db071ec59..0000000000 --- a/django/contrib/sitemaps/management/commands/ping_google.py +++ /dev/null @@ -1,16 +0,0 @@ -from django.contrib.sitemaps import ping_google -from django.core.management.base import BaseCommand - - -class Command(BaseCommand): - help = "Ping Google with an updated sitemap, pass optional url of sitemap" - - def add_arguments(self, parser): - parser.add_argument("sitemap_url", nargs="?") - parser.add_argument("--sitemap-uses-http", action="store_true") - - def handle(self, *args, **options): - ping_google( - sitemap_url=options["sitemap_url"], - sitemap_uses_https=not options["sitemap_uses_http"], - ) diff --git a/docs/ref/contrib/sitemaps.txt b/docs/ref/contrib/sitemaps.txt index 57bcc81a01..020eaf03ff 100644 --- a/docs/ref/contrib/sitemaps.txt +++ b/docs/ref/contrib/sitemaps.txt @@ -588,78 +588,3 @@ generate a Google News compatible sitemap: .. _`Google news sitemaps`: https://support.google.com/news/publisher-center/answer/9606710 - -Pinging Google -============== - -You may want to "ping" Google when your sitemap changes, to let it know to -reindex your site. The sitemaps framework provides a function to do just -that: :func:`django.contrib.sitemaps.ping_google()`. - -.. function:: ping_google(sitemap_url=None, ping_url=PING_URL, sitemap_uses_https=True) - - ``ping_google`` takes these optional arguments: - - * ``sitemap_url`` - The absolute path to your site's sitemap (e.g., - :file:`'/sitemap.xml'`). - - If this argument isn't provided, ``ping_google`` will perform a reverse - lookup in your URLconf, for URLs named - ``'django.contrib.sitemaps.views.index'`` and then - ``'django.contrib.sitemaps.views.sitemap'`` (without further arguments) to - automatically determine the sitemap URL. - - * ``ping_url`` - Defaults to Google's Ping Tool: - https://www.google.com/webmasters/tools/ping. - - * ``sitemap_uses_https`` - Set to ``False`` if your site uses ``http`` - rather than ``https``. - - :func:`ping_google` raises the exception - ``django.contrib.sitemaps.SitemapNotFound`` if it cannot determine your - sitemap URL. - -.. admonition:: Register with Google first! - - The :func:`ping_google` command only works if you have registered your - site with `Google Search Console`_. - -.. _`Google Search Console`: https://search.google.com/search-console/welcome - -One useful way to call :func:`ping_google` is from a model's ``save()`` -method:: - - from django.contrib.sitemaps import ping_google - - - class Entry(models.Model): - # ... - def save(self, force_insert=False, force_update=False): - super().save(force_insert, force_update) - try: - ping_google() - except Exception: - # Bare 'except' because we could get a variety - # of HTTP-related exceptions. - pass - -A more efficient solution, however, would be to call :func:`ping_google` from a -cron script, or some other scheduled task. The function makes an HTTP request -to Google's servers, so you may not want to introduce that network overhead -each time you call ``save()``. - -Pinging Google via ``manage.py`` --------------------------------- - -.. django-admin:: ping_google [sitemap_url] - -Once the sitemaps application is added to your project, you may also -ping Google using the ``ping_google`` management command: - -.. code-block:: shell - - python manage.py ping_google [/sitemap.xml] - -.. django-admin-option:: --sitemap-uses-http - -Use this option if your sitemap uses ``http`` rather than ``https``. diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt index 110b1e802a..a46910f9f3 100644 --- a/docs/ref/django-admin.txt +++ b/docs/ref/django-admin.txt @@ -1759,18 +1759,6 @@ documentation. Can be run as a cron job or directly to clean out expired sessions. -``django.contrib.sitemaps`` ---------------------------- - -``ping_google`` -~~~~~~~~~~~~~~~ - -This command is only available if the :doc:`Sitemaps framework -` (``django.contrib.sitemaps``) is installed. - -Please refer to its :djadmin:`description ` in the Sitemaps -documentation. - ``django.contrib.staticfiles`` ------------------------------ diff --git a/docs/releases/2.2.txt b/docs/releases/2.2.txt index e27fdbbca8..664549473e 100644 --- a/docs/releases/2.2.txt +++ b/docs/releases/2.2.txt @@ -455,10 +455,10 @@ Miscellaneous passed as a value to encode because ``None`` can't be encoded in GET and POST data. Either pass an empty string or omit the value. -* The :djadmin:`ping_google` management command now defaults to ``https`` +* The ``ping_google`` management command now defaults to ``https`` instead of ``http`` for the sitemap's URL. If your site uses http, use the - new :option:`ping_google --sitemap-uses-http` option. If you use the - :func:`~django.contrib.sitemaps.ping_google` function, set the new + new ``ping_google --sitemap-uses-http`` option. If you use the + ``django.contrib.sitemaps.ping_google`` function, set the new ``sitemap_uses_https`` argument to ``False``. * :djadmin:`runserver` no longer supports ``pyinotify`` (replaced by Watchman). diff --git a/docs/releases/5.0.txt b/docs/releases/5.0.txt index aa397e8cb0..722d3bcf0b 100644 --- a/docs/releases/5.0.txt +++ b/docs/releases/5.0.txt @@ -443,6 +443,15 @@ backends. * Support for GEOS 3.6 and 3.7 is removed. +:mod:`django.contrib.sitemaps` +------------------------------ + +* The ``django.contrib.sitemaps.ping_google()`` function and the + ``ping_google`` management command are removed as the Google + Sitemaps ping endpoint is deprecated and will be removed in January 2024. + +* The ``django.contrib.sitemaps.SitemapNotFound`` exception class is removed. + Using ``create_defaults__exact`` may now be required with ``QuerySet.update_or_create()`` ----------------------------------------------------------------------------------------- diff --git a/tests/sitemaps_tests/test_management.py b/tests/sitemaps_tests/test_management.py deleted file mode 100644 index aa797216e4..0000000000 --- a/tests/sitemaps_tests/test_management.py +++ /dev/null @@ -1,18 +0,0 @@ -from unittest import mock - -from django.core.management import call_command - -from .base import SitemapTestsBase - - -@mock.patch("django.contrib.sitemaps.management.commands.ping_google.ping_google") -class PingGoogleTests(SitemapTestsBase): - def test_default(self, ping_google_func): - call_command("ping_google") - ping_google_func.assert_called_with(sitemap_url=None, sitemap_uses_https=True) - - def test_args(self, ping_google_func): - call_command("ping_google", "foo.xml", "--sitemap-uses-http") - ping_google_func.assert_called_with( - sitemap_url="foo.xml", sitemap_uses_https=False - ) diff --git a/tests/sitemaps_tests/test_utils.py b/tests/sitemaps_tests/test_utils.py deleted file mode 100644 index 3aba9b5a1a..0000000000 --- a/tests/sitemaps_tests/test_utils.py +++ /dev/null @@ -1,59 +0,0 @@ -from unittest import mock -from urllib.parse import urlencode - -from django.contrib.sitemaps import SitemapNotFound, _get_sitemap_full_url, ping_google -from django.core.exceptions import ImproperlyConfigured -from django.test import modify_settings, override_settings - -from .base import SitemapTestsBase - - -class PingGoogleTests(SitemapTestsBase): - @override_settings(ROOT_URLCONF="sitemaps_tests.urls.sitemap_only") - @mock.patch("django.contrib.sitemaps.urlopen") - def test_something(self, urlopen): - ping_google() - params = urlencode( - {"sitemap": "https://example.com/sitemap-without-entries/sitemap.xml"} - ) - full_url = "https://www.google.com/webmasters/tools/ping?%s" % params - urlopen.assert_called_with(full_url) - - @override_settings(ROOT_URLCONF="sitemaps_tests.urls.sitemap_only") - def test_get_sitemap_full_url_global(self): - self.assertEqual( - _get_sitemap_full_url(None), - "https://example.com/sitemap-without-entries/sitemap.xml", - ) - - @override_settings(ROOT_URLCONF="sitemaps_tests.urls.index_only") - def test_get_sitemap_full_url_index(self): - self.assertEqual( - _get_sitemap_full_url(None), "https://example.com/simple/index.xml" - ) - - @override_settings(ROOT_URLCONF="sitemaps_tests.urls.empty") - def test_get_sitemap_full_url_not_detected(self): - msg = ( - "You didn't provide a sitemap_url, and the sitemap URL couldn't be " - "auto-detected." - ) - with self.assertRaisesMessage(SitemapNotFound, msg): - _get_sitemap_full_url(None) - - def test_get_sitemap_full_url_exact_url(self): - self.assertEqual( - _get_sitemap_full_url("/foo.xml"), "https://example.com/foo.xml" - ) - - def test_get_sitemap_full_url_insecure(self): - self.assertEqual( - _get_sitemap_full_url("/foo.xml", sitemap_uses_https=False), - "http://example.com/foo.xml", - ) - - @modify_settings(INSTALLED_APPS={"remove": "django.contrib.sites"}) - def test_get_sitemap_full_url_no_sites(self): - msg = "ping_google requires django.contrib.sites, which isn't installed." - with self.assertRaisesMessage(ImproperlyConfigured, msg): - _get_sitemap_full_url(None) diff --git a/tests/sitemaps_tests/urls/empty.py b/tests/sitemaps_tests/urls/empty.py deleted file mode 100644 index 637600f58a..0000000000 --- a/tests/sitemaps_tests/urls/empty.py +++ /dev/null @@ -1 +0,0 @@ -urlpatterns = [] diff --git a/tests/sitemaps_tests/urls/index_only.py b/tests/sitemaps_tests/urls/index_only.py deleted file mode 100644 index 238172b2e8..0000000000 --- a/tests/sitemaps_tests/urls/index_only.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.contrib.sitemaps import views -from django.urls import path - -from .http import simple_sitemaps - -urlpatterns = [ - path( - "simple/index.xml", - views.index, - {"sitemaps": simple_sitemaps}, - name="django.contrib.sitemaps.views.index", - ), -] diff --git a/tests/sitemaps_tests/urls/sitemap_only.py b/tests/sitemaps_tests/urls/sitemap_only.py deleted file mode 100644 index 1b23977b28..0000000000 --- a/tests/sitemaps_tests/urls/sitemap_only.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.contrib.sitemaps import views -from django.urls import path - -urlpatterns = [ - path( - "sitemap-without-entries/sitemap.xml", - views.sitemap, - {"sitemaps": {}}, - name="django.contrib.sitemaps.views.sitemap", - ), -]