1
0
mirror of https://github.com/django/django.git synced 2025-01-03 06:55:47 +00:00

Fixed #34688 -- Removed contrib.sitemaps.ping_google() and ping_google management command.

Thanks Joachim Jablon for the report.

Google has deprecated the sitemap ping endpoint, and will be removing
it in 6 months ~January 2024.
This commit is contained in:
Andrew Northall 2023-07-02 21:48:56 +01:00 committed by Mariusz Felisiak
parent 2584783f46
commit 6d427288e4
13 changed files with 12 additions and 259 deletions

View File

@ -1,60 +1,9 @@
from urllib.parse import urlencode
from urllib.request import urlopen
from django.apps import apps as django_apps from django.apps import apps as django_apps
from django.conf import settings from django.conf import settings
from django.core import paginator from django.core import paginator
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.urls import NoReverseMatch, reverse
from django.utils import translation 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: class Sitemap:
# This limit is defined by Google. See the index documentation at # This limit is defined by Google. See the index documentation at

View File

@ -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"],
)

View File

@ -588,78 +588,3 @@ generate a Google News compatible sitemap:
</urlset> </urlset>
.. _`Google news sitemaps`: https://support.google.com/news/publisher-center/answer/9606710 .. _`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``.

View File

@ -1759,18 +1759,6 @@ documentation.
Can be run as a cron job or directly to clean out expired sessions. 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
</ref/contrib/sitemaps>` (``django.contrib.sitemaps``) is installed.
Please refer to its :djadmin:`description <ping_google>` in the Sitemaps
documentation.
``django.contrib.staticfiles`` ``django.contrib.staticfiles``
------------------------------ ------------------------------

View File

@ -455,10 +455,10 @@ Miscellaneous
passed as a value to encode because ``None`` can't be encoded in GET and POST 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. 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 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 new ``ping_google --sitemap-uses-http`` option. If you use the
:func:`~django.contrib.sitemaps.ping_google` function, set the new ``django.contrib.sitemaps.ping_google`` function, set the new
``sitemap_uses_https`` argument to ``False``. ``sitemap_uses_https`` argument to ``False``.
* :djadmin:`runserver` no longer supports ``pyinotify`` (replaced by Watchman). * :djadmin:`runserver` no longer supports ``pyinotify`` (replaced by Watchman).

View File

@ -443,6 +443,15 @@ backends.
* Support for GEOS 3.6 and 3.7 is removed. * 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()`` Using ``create_defaults__exact`` may now be required with ``QuerySet.update_or_create()``
----------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------

View File

@ -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
)

View File

@ -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)

View File

@ -1 +0,0 @@
urlpatterns = []

View File

@ -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",
),
]

View File

@ -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",
),
]