mirror of
https://github.com/django/django.git
synced 2025-04-10 08:19:39 +00:00
Merge branch 'django:main' into skushagra-patch-1-issue-35119
This commit is contained in:
commit
3d4e918620
2
AUTHORS
2
AUTHORS
@ -1087,6 +1087,6 @@ A big THANK YOU goes to:
|
||||
|
||||
Ian Bicking for convincing Adrian to ditch code generation.
|
||||
|
||||
Mark Pilgrim for "Dive Into Python" (https://www.diveinto.org/python3/).
|
||||
Mark Pilgrim for "Dive Into Python" (https://diveintopython3.net/).
|
||||
|
||||
Guido van Rossum for creating Python.
|
||||
|
@ -39,6 +39,7 @@
|
||||
True True
|
||||
"""
|
||||
import sys
|
||||
import warnings
|
||||
from binascii import b2a_hex
|
||||
from ctypes import byref, c_char_p, c_double, c_ubyte, c_void_p, string_at
|
||||
|
||||
@ -50,6 +51,7 @@ from django.contrib.gis.gdal.prototypes import geom as capi
|
||||
from django.contrib.gis.gdal.prototypes import srs as srs_api
|
||||
from django.contrib.gis.gdal.srs import CoordTransform, SpatialReference
|
||||
from django.contrib.gis.geometry import hex_regex, json_regex, wkt_regex
|
||||
from django.utils.deprecation import RemovedInDjango60Warning
|
||||
from django.utils.encoding import force_bytes
|
||||
|
||||
|
||||
@ -206,18 +208,21 @@ class OGRGeometry(GDALBase):
|
||||
"Return 0 for points, 1 for lines, and 2 for surfaces."
|
||||
return capi.get_dims(self.ptr)
|
||||
|
||||
def _get_coord_dim(self):
|
||||
@property
|
||||
def coord_dim(self):
|
||||
"Return the coordinate dimension of the Geometry."
|
||||
return capi.get_coord_dim(self.ptr)
|
||||
|
||||
def _set_coord_dim(self, dim):
|
||||
# RemovedInDjango60Warning
|
||||
@coord_dim.setter
|
||||
def coord_dim(self, dim):
|
||||
"Set the coordinate dimension of this Geometry."
|
||||
msg = "coord_dim setter is deprecated. Use set_3d() instead."
|
||||
warnings.warn(msg, RemovedInDjango60Warning, stacklevel=2)
|
||||
if dim not in (2, 3):
|
||||
raise ValueError("Geometry dimension must be either 2 or 3")
|
||||
capi.set_coord_dim(self.ptr, dim)
|
||||
|
||||
coord_dim = property(_get_coord_dim, _set_coord_dim)
|
||||
|
||||
@property
|
||||
def geom_count(self):
|
||||
"Return the number of elements in this Geometry."
|
||||
|
@ -17,6 +17,7 @@ from django.db.utils import (
|
||||
from django.utils.connection import ConnectionProxy
|
||||
|
||||
__all__ = [
|
||||
"close_old_connections",
|
||||
"connection",
|
||||
"connections",
|
||||
"router",
|
||||
|
@ -95,12 +95,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
"db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests."
|
||||
"test_trunc_week_before_1000",
|
||||
},
|
||||
"Oracle extracts seconds including fractional seconds (#33517).": {
|
||||
"db_functions.datetime.test_extract_trunc.DateFunctionTests."
|
||||
"test_extract_second_func_no_fractional",
|
||||
"db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests."
|
||||
"test_extract_second_func_no_fractional",
|
||||
},
|
||||
"Oracle doesn't support bitwise XOR.": {
|
||||
"expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor",
|
||||
"expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_null",
|
||||
|
@ -165,6 +165,9 @@ END;
|
||||
|
||||
def datetime_extract_sql(self, lookup_type, sql, params, tzname):
|
||||
sql, params = self._convert_sql_to_tz(sql, params, tzname)
|
||||
if lookup_type == "second":
|
||||
# Truncate fractional seconds.
|
||||
return f"FLOOR(EXTRACT(SECOND FROM {sql}))", params
|
||||
return self.date_extract_sql(lookup_type, sql, params)
|
||||
|
||||
def datetime_trunc_sql(self, lookup_type, sql, params, tzname):
|
||||
@ -188,6 +191,12 @@ END;
|
||||
return f"CAST({sql} AS DATE)", params
|
||||
return f"TRUNC({sql}, %s)", (*params, trunc_param)
|
||||
|
||||
def time_extract_sql(self, lookup_type, sql, params):
|
||||
if lookup_type == "second":
|
||||
# Truncate fractional seconds.
|
||||
return f"FLOOR(EXTRACT(SECOND FROM {sql}))", params
|
||||
return self.date_extract_sql(lookup_type, sql, params)
|
||||
|
||||
def time_trunc_sql(self, lookup_type, sql, params, tzname=None):
|
||||
# The implementation is similar to `datetime_trunc_sql` as both
|
||||
# `DateTimeField` and `TimeField` are stored as TIMESTAMP where
|
||||
|
@ -261,6 +261,10 @@ class Field:
|
||||
result.validators = self.validators[:]
|
||||
return result
|
||||
|
||||
def _clean_bound_field(self, bf):
|
||||
value = bf.initial if self.disabled else bf.data
|
||||
return self.clean(value)
|
||||
|
||||
|
||||
class CharField(Field):
|
||||
def __init__(
|
||||
@ -694,6 +698,10 @@ class FileField(Field):
|
||||
def has_changed(self, initial, data):
|
||||
return not self.disabled and data is not None
|
||||
|
||||
def _clean_bound_field(self, bf):
|
||||
value = bf.initial if self.disabled else bf.data
|
||||
return self.clean(value, bf.initial)
|
||||
|
||||
|
||||
class ImageField(FileField):
|
||||
default_validators = [validators.validate_image_file_extension]
|
||||
|
@ -6,7 +6,7 @@ import copy
|
||||
import datetime
|
||||
|
||||
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
|
||||
from django.forms.fields import Field, FileField
|
||||
from django.forms.fields import Field
|
||||
from django.forms.utils import ErrorDict, ErrorList, RenderableFormMixin
|
||||
from django.forms.widgets import Media, MediaDefiningClass
|
||||
from django.utils.datastructures import MultiValueDict
|
||||
@ -329,13 +329,8 @@ class BaseForm(RenderableFormMixin):
|
||||
def _clean_fields(self):
|
||||
for name, bf in self._bound_items():
|
||||
field = bf.field
|
||||
value = bf.initial if field.disabled else bf.data
|
||||
try:
|
||||
if isinstance(field, FileField):
|
||||
value = field.clean(value, bf.initial)
|
||||
else:
|
||||
value = field.clean(value)
|
||||
self.cleaned_data[name] = value
|
||||
self.cleaned_data[name] = field._clean_bound_field(bf)
|
||||
if hasattr(self, "clean_%s" % name):
|
||||
value = getattr(self, "clean_%s" % name)()
|
||||
self.cleaned_data[name] = value
|
||||
|
@ -71,6 +71,9 @@ details on these changes.
|
||||
* Support for passing positional arguments to ``Model.save()`` and
|
||||
``Model.asave()`` will be removed.
|
||||
|
||||
* The setter for ``django.contrib.gis.gdal.OGRGeometry.coord_dim`` will be
|
||||
removed.
|
||||
|
||||
.. _deprecation-removed-in-5.1:
|
||||
|
||||
5.1
|
||||
|
@ -27,8 +27,8 @@ For this tutorial, we expect that you have at least a basic understanding of
|
||||
how Django works. This means you should be comfortable going through the
|
||||
existing tutorials on :doc:`writing your first Django app</intro/tutorial01>`.
|
||||
In addition, you should have a good understanding of Python itself. But if you
|
||||
don't, `Dive Into Python`__ is a fantastic (and free) online book for
|
||||
beginning Python programmers.
|
||||
don't, `Dive Into Python`_ is a fantastic (and free) online book for beginning
|
||||
Python programmers.
|
||||
|
||||
Those of you who are unfamiliar with version control systems and Trac will find
|
||||
that this tutorial and its links include just enough information to get started.
|
||||
@ -45,8 +45,8 @@ so that it can be of use to the widest audience.
|
||||
`#django-dev on irc.libera.chat`__ to chat with other Django users who
|
||||
might be able to help.
|
||||
|
||||
__ https://diveinto.org/python3/table-of-contents.html
|
||||
__ https://web.libera.chat/#django-dev
|
||||
.. _Dive Into Python: https://diveintopython3.net/
|
||||
.. _Django Forum: https://forum.djangoproject.com/
|
||||
|
||||
What does this tutorial cover?
|
||||
@ -350,7 +350,7 @@ This test checks that the ``make_toast()`` returns ``'toast'``.
|
||||
* After reading those, if you want something a little meatier to sink
|
||||
your teeth into, there's always the Python :mod:`unittest` documentation.
|
||||
|
||||
__ https://diveinto.org/python3/unit-testing.html
|
||||
__ https://diveintopython3.net/unit-testing.html
|
||||
|
||||
Running your new test
|
||||
---------------------
|
||||
|
@ -32,10 +32,12 @@ place: read this material to quickly get up and running.
|
||||
`list of Python resources for non-programmers`_
|
||||
|
||||
If you already know a few other languages and want to get up to speed with
|
||||
Python quickly, we recommend `Dive Into Python`_. If that's not quite your
|
||||
style, there are many other `books about Python`_.
|
||||
Python quickly, we recommend referring the official
|
||||
`Python documentation`_, which provides comprehensive and authoritative
|
||||
information about the language, as well as links to other resources such as
|
||||
a list of `books about Python`_.
|
||||
|
||||
.. _python: https://www.python.org/
|
||||
.. _list of Python resources for non-programmers: https://wiki.python.org/moin/BeginnersGuide/NonProgrammers
|
||||
.. _Dive Into Python: https://diveinto.org/python3/table-of-contents.html
|
||||
.. _Python documentation: https://docs.python.org/3/
|
||||
.. _books about Python: https://wiki.python.org/moin/PythonBooks
|
||||
|
@ -76,7 +76,7 @@ After the previous tutorials, our project should look like this:
|
||||
static/
|
||||
polls/
|
||||
images/
|
||||
background.gif
|
||||
background.png
|
||||
style.css
|
||||
templates/
|
||||
polls/
|
||||
|
@ -553,8 +553,12 @@ coordinate transformation:
|
||||
|
||||
.. attribute:: coord_dim
|
||||
|
||||
Returns or sets the coordinate dimension of this geometry. For example, the
|
||||
value would be 2 for two-dimensional geometries.
|
||||
Returns the coordinate dimension of this geometry. For example, the value
|
||||
would be 2 for two-dimensional geometries.
|
||||
|
||||
.. deprecated:: 5.1
|
||||
|
||||
The ``coord_dim`` setter is deprecated. Use :meth:`.set_3d` instead.
|
||||
|
||||
.. attribute:: is_3d
|
||||
|
||||
|
@ -99,7 +99,8 @@ connections.
|
||||
|
||||
If a connection is created in a long-running process, outside of Django’s
|
||||
request-response cycle, the connection will remain open until explicitly
|
||||
closed, or timeout occurs.
|
||||
closed, or timeout occurs. You can use ``django.db.close_old_connections()`` to
|
||||
close all old or unusable connections.
|
||||
|
||||
Encoding
|
||||
--------
|
||||
|
@ -1797,9 +1797,9 @@ allows for the following options by default:
|
||||
|
||||
.. django-admin-option:: --pythonpath PYTHONPATH
|
||||
|
||||
Adds the given filesystem path to the Python `import search path`_. If this
|
||||
isn't provided, ``django-admin`` will use the :envvar:`PYTHONPATH` environment
|
||||
variable.
|
||||
Adds the given filesystem path to the Python :py:data:`sys.path` module
|
||||
attribute. If this isn't provided, ``django-admin`` will use the
|
||||
:envvar:`PYTHONPATH` environment variable.
|
||||
|
||||
This option is unnecessary in ``manage.py``, because it takes care of setting
|
||||
the Python path for you.
|
||||
@ -1810,8 +1810,6 @@ Example usage:
|
||||
|
||||
django-admin migrate --pythonpath='/home/djangoprojects/myproject'
|
||||
|
||||
.. _import search path: https://diveinto.org/python3/your-first-python-program.html#importsearchpath
|
||||
|
||||
.. django-admin-option:: --settings SETTINGS
|
||||
|
||||
Specifies the settings module to use. The settings module should be in Python
|
||||
|
@ -2484,8 +2484,8 @@ individual elements of the sequence.
|
||||
|
||||
Returns a slice of the list.
|
||||
|
||||
Uses the same syntax as Python's list slicing. See
|
||||
https://diveinto.org/python3/native-datatypes.html#slicinglists for an
|
||||
Uses the same syntax as Python's list slicing. See the `Python documentation
|
||||
<https://docs.python.org/3/tutorial/introduction.html#lists>`_ for an
|
||||
introduction.
|
||||
|
||||
Example:
|
||||
|
@ -378,6 +378,9 @@ Miscellaneous
|
||||
* Passing positional arguments to :meth:`.Model.save` and :meth:`.Model.asave`
|
||||
is deprecated in favor of keyword-only arguments.
|
||||
|
||||
* Setting ``django.contrib.gis.gdal.OGRGeometry.coord_dim`` is deprecated. Use
|
||||
:meth:`~django.contrib.gis.gdal.OGRGeometry.set_3d` instead.
|
||||
|
||||
Features removed in 5.1
|
||||
=======================
|
||||
|
||||
|
@ -1608,7 +1608,7 @@ Helper functions
|
||||
Defaults to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied.
|
||||
|
||||
* ``redirect_field_name``: The name of a ``GET`` field containing the
|
||||
URL to redirect to after log out. Overrides ``next`` if the given
|
||||
URL to redirect to after login. Overrides ``next`` if the given
|
||||
``GET`` parameter is passed.
|
||||
|
||||
.. _built-in-auth-forms:
|
||||
|
@ -44,9 +44,8 @@ by using an environment variable, :envvar:`DJANGO_SETTINGS_MODULE`.
|
||||
|
||||
The value of :envvar:`DJANGO_SETTINGS_MODULE` should be in Python path syntax,
|
||||
e.g. ``mysite.settings``. Note that the settings module should be on the
|
||||
Python `import search path`_.
|
||||
Python :py:data:`sys.path`.
|
||||
|
||||
.. _import search path: https://diveinto.org/python3/your-first-python-program.html#importsearchpath
|
||||
|
||||
The ``django-admin`` utility
|
||||
----------------------------
|
||||
|
@ -11,6 +11,7 @@ from django.contrib.gis.gdal import (
|
||||
from django.template import Context
|
||||
from django.template.engine import Engine
|
||||
from django.test import SimpleTestCase
|
||||
from django.utils.deprecation import RemovedInDjango60Warning
|
||||
|
||||
from ..test_data import TestDataMixin
|
||||
|
||||
@ -727,3 +728,95 @@ class OGRGeomTest(SimpleTestCase, TestDataMixin):
|
||||
msg = "Input to 'set_3d' must be a boolean, got 'None'"
|
||||
with self.assertRaisesMessage(ValueError, msg):
|
||||
geom.set_3d(None)
|
||||
|
||||
def test_wkt_and_wkb_output(self):
|
||||
tests = [
|
||||
# 2D
|
||||
("POINT (1 2)", "0101000000000000000000f03f0000000000000040"),
|
||||
(
|
||||
"LINESTRING (30 10,10 30)",
|
||||
"0102000000020000000000000000003e400000000000002"
|
||||
"44000000000000024400000000000003e40",
|
||||
),
|
||||
(
|
||||
"POLYGON ((30 10,40 40,20 40,30 10))",
|
||||
"010300000001000000040000000000000000003e400000000000002440000000000000"
|
||||
"44400000000000004440000000000000344000000000000044400000000000003e4000"
|
||||
"00000000002440",
|
||||
),
|
||||
(
|
||||
"MULTIPOINT (10 40,40 30)",
|
||||
"0104000000020000000101000000000000000000244000000000000044400101000000"
|
||||
"00000000000044400000000000003e40",
|
||||
),
|
||||
(
|
||||
"MULTILINESTRING ((10 10,20 20),(40 40,30 30,40 20))",
|
||||
"0105000000020000000102000000020000000000000000002440000000000000244000"
|
||||
"0000000000344000000000000034400102000000030000000000000000004440000000"
|
||||
"00000044400000000000003e400000000000003e400000000000004440000000000000"
|
||||
"3440",
|
||||
),
|
||||
(
|
||||
"MULTIPOLYGON (((30 20,45 40,10 40,30 20)),((15 5,40 10,10 20,15 5)))",
|
||||
"010600000002000000010300000001000000040000000000000000003e400000000000"
|
||||
"0034400000000000804640000000000000444000000000000024400000000000004440"
|
||||
"0000000000003e40000000000000344001030000000100000004000000000000000000"
|
||||
"2e40000000000000144000000000000044400000000000002440000000000000244000"
|
||||
"000000000034400000000000002e400000000000001440",
|
||||
),
|
||||
(
|
||||
"GEOMETRYCOLLECTION (POINT (40 10))",
|
||||
"010700000001000000010100000000000000000044400000000000002440",
|
||||
),
|
||||
# 3D
|
||||
(
|
||||
"POINT (1 2 3)",
|
||||
"0101000080000000000000f03f00000000000000400000000000000840",
|
||||
),
|
||||
(
|
||||
"LINESTRING (30 10 3,10 30 3)",
|
||||
"0102000080020000000000000000003e40000000000000244000000000000008400000"
|
||||
"0000000024400000000000003e400000000000000840",
|
||||
),
|
||||
(
|
||||
"POLYGON ((30 10 3,40 40 3,30 10 3))",
|
||||
"010300008001000000030000000000000000003e400000000000002440000000000000"
|
||||
"08400000000000004440000000000000444000000000000008400000000000003e4000"
|
||||
"000000000024400000000000000840",
|
||||
),
|
||||
(
|
||||
"MULTIPOINT (10 40 3,40 30 3)",
|
||||
"0104000080020000000101000080000000000000244000000000000044400000000000"
|
||||
"000840010100008000000000000044400000000000003e400000000000000840",
|
||||
),
|
||||
(
|
||||
"MULTILINESTRING ((10 10 3,20 20 3))",
|
||||
"0105000080010000000102000080020000000000000000002440000000000000244000"
|
||||
"00000000000840000000000000344000000000000034400000000000000840",
|
||||
),
|
||||
(
|
||||
"MULTIPOLYGON (((30 20 3,45 40 3,30 20 3)))",
|
||||
"010600008001000000010300008001000000030000000000000000003e400000000000"
|
||||
"0034400000000000000840000000000080464000000000000044400000000000000840"
|
||||
"0000000000003e4000000000000034400000000000000840",
|
||||
),
|
||||
(
|
||||
"GEOMETRYCOLLECTION (POINT (40 10 3))",
|
||||
"0107000080010000000101000080000000000000444000000000000024400000000000"
|
||||
"000840",
|
||||
),
|
||||
]
|
||||
for geom, wkb in tests:
|
||||
with self.subTest(geom=geom):
|
||||
g = OGRGeometry(geom)
|
||||
self.assertEqual(g.wkt, geom)
|
||||
self.assertEqual(g.wkb.hex(), wkb)
|
||||
|
||||
|
||||
class DeprecationTests(SimpleTestCase):
|
||||
def test_coord_setter_deprecation(self):
|
||||
geom = OGRGeometry("POINT (1 2)")
|
||||
msg = "coord_dim setter is deprecated. Use set_3d() instead."
|
||||
with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
|
||||
geom.coord_dim = 3
|
||||
self.assertEqual(geom.coord_dim, 3)
|
||||
|
Loading…
x
Reference in New Issue
Block a user