xdjango-postgres-extra 2.1.1__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- xdjango_postgres_extra-2.2.0/PKG-INFO +209 -0
- xdjango_postgres_extra-2.2.0/README.md +111 -0
- xdjango_postgres_extra-2.2.0/psqlextra/_version.py +1 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/introspection.py +16 -2
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/create_partitioned_model.py +10 -4
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/schema.py +10 -2
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/setup.py +2 -1
- xdjango_postgres_extra-2.2.0/tests/test_django_61_compatibility.py +79 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_make_migrations.py +6 -1
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema_editor_clone_model_to_schema.py +11 -3
- xdjango_postgres_extra-2.2.0/xdjango_postgres_extra.egg-info/PKG-INFO +209 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/xdjango_postgres_extra.egg-info/SOURCES.txt +1 -0
- xdjango_postgres_extra-2.1.1/PKG-INFO +0 -206
- xdjango_postgres_extra-2.1.1/README.md +0 -112
- xdjango_postgres_extra-2.1.1/psqlextra/_version.py +0 -1
- xdjango_postgres_extra-2.1.1/xdjango_postgres_extra.egg-info/PKG-INFO +0 -206
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/LICENSE +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/apps.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/base.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/base_impl.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/add_default_partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/add_hash_partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/add_list_partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/add_range_partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/apply_state.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/create_materialized_view_model.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/create_view_model.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_default_partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_hash_partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_list_partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_materialized_view_model.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_partitioned_model.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_range_partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/delete_view_model.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/operations/partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/patched_autodetector.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/patched_migrations.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/patched_project_state.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/state/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/state/materialized_view.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/state/model.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/state/partitioning.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/migrations/state/view.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/operations.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/side_effects/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/side_effects/hstore_required.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/side_effects/hstore_unique.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/compiler.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/contrib/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/contrib/expressions.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/contrib/model_data_migrator.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/contrib/static_row.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/contrib/transaction.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/error.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/expressions.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/fields/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/fields/hstore_field.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/indexes/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/indexes/case_insensitive_unique_index.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/indexes/conditional_unique_index.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/indexes/unique_index.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/introspect/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/introspect/fields.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/introspect/models.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/locking.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/lookups.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/management/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/management/commands/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/management/commands/pgmakemigrations.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/management/commands/pgpartition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/management/commands/pgrefreshmv.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/manager/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/manager/manager.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/models/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/models/base.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/models/options.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/models/partitioned.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/models/view.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/__init__.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/config.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/constants.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/current_time_strategy.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/error.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/manager.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/plan.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/range_partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/range_strategy.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/shorthands.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/strategy.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/time_partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/time_partition_size.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/partitioning/time_strategy.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/py.typed +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/query.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/schema.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/settings.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/sql.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/type_assertions.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/types.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/util.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/pyproject.toml +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/setup.cfg +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_append_caller_to_sql.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_case_insensitive_unique_index.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_conditional_unique_index.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_db_backend.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_django_6_compatibility.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_hstore_autodetect.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_hstore_field.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_hstore_required.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_hstore_unique.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_insert.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_introspect.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_locking.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_lookups.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_management_command_partition.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_manager.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_manager_context.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_materialized_view_model.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_migration_operations.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_on_conflict.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_on_conflict_nothing.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_on_conflict_update.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_partitioned_model.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_partitioned_model_state.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_partitioning_manager.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_partitioning_time.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_query.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_query_values.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema_editor_alter_schema.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema_editor_partitioning.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema_editor_storage_settings.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema_editor_vacuum.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_schema_editor_view.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_settings.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_unique_index.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_upsert.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/tests/test_view_models.py +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/xdjango_postgres_extra.egg-info/dependency_links.txt +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/xdjango_postgres_extra.egg-info/requires.txt +0 -0
- {xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/xdjango_postgres_extra.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xdjango-postgres-extra
|
|
3
|
+
Version: 2.2.0
|
|
4
|
+
Summary: Bringing all of PostgreSQL's awesomeness to Django.
|
|
5
|
+
Home-page: https://github.com/SectorLabs/django-postgres-extra
|
|
6
|
+
Author: Sector Labs
|
|
7
|
+
Author-email: open-source@sectorlabs.ro
|
|
8
|
+
License: MIT License
|
|
9
|
+
Keywords: django,postgres,extra,hstore,upsert,partioning,materialized,view
|
|
10
|
+
Classifier: Environment :: Web Environment
|
|
11
|
+
Classifier: Framework :: Django
|
|
12
|
+
Classifier: Framework :: Django :: 6.0
|
|
13
|
+
Classifier: Framework :: Django :: 6.1
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
27
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
28
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
29
|
+
Requires-Python: >=3.6
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Requires-Dist: Django<7.0,>=2.0
|
|
33
|
+
Requires-Dist: python-dateutil<=3.0.0,>=2.8.0
|
|
34
|
+
Requires-Dist: dataclasses; python_version <= "3.6"
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: poethepoet==0.34.0; python_version >= "3.9" and extra == "dev"
|
|
37
|
+
Requires-Dist: poethepoet==0.30.0; (python_version >= "3.8" and python_version < "3.9") and extra == "dev"
|
|
38
|
+
Requires-Dist: poethepoet==0.19.0; (python_version >= "3.7" and python_version < "3.8") and extra == "dev"
|
|
39
|
+
Requires-Dist: poethepoet==0.13.1; (python_version >= "3.6" and python_version < "3.7") and extra == "dev"
|
|
40
|
+
Provides-Extra: test
|
|
41
|
+
Requires-Dist: psycopg2==2.9.10; python_version >= "3.8" and extra == "test"
|
|
42
|
+
Requires-Dist: psycopg2==2.9.9; (python_version >= "3.7" and python_version < "3.8") and extra == "test"
|
|
43
|
+
Requires-Dist: psycopg2==2.9.8; (python_version >= "3.6" and python_version < "3.7") and extra == "test"
|
|
44
|
+
Requires-Dist: types-psycopg2==2.9.21.20250516; python_version >= "3.9" and extra == "test"
|
|
45
|
+
Requires-Dist: types-psycopg2==2.9.8; (python_version >= "3.6" and python_version < "3.9") and extra == "test"
|
|
46
|
+
Requires-Dist: pytest==8.4.0; python_version > "3.8" and extra == "test"
|
|
47
|
+
Requires-Dist: pytest==7.0.1; python_version <= "3.8" and extra == "test"
|
|
48
|
+
Requires-Dist: pytest-benchmark==5.1.0; python_version > "3.8" and extra == "test"
|
|
49
|
+
Requires-Dist: pytest-benchmark==3.4.1; python_version <= "3.8" and extra == "test"
|
|
50
|
+
Requires-Dist: pytest-django==4.11.1; python_version > "3.7" and extra == "test"
|
|
51
|
+
Requires-Dist: pytest-django==4.5.2; python_version <= "3.7" and extra == "test"
|
|
52
|
+
Requires-Dist: pytest-cov==6.1.1; python_version > "3.8" and extra == "test"
|
|
53
|
+
Requires-Dist: pytest-cov==4.0.0; python_version <= "3.8" and extra == "test"
|
|
54
|
+
Requires-Dist: coverage==7.8.2; python_version > "3.8" and extra == "test"
|
|
55
|
+
Requires-Dist: coverage==7.6.1; (python_version >= "3.8" and python_version <= "3.8") and extra == "test"
|
|
56
|
+
Requires-Dist: coverage==6.2; python_version <= "3.7" and extra == "test"
|
|
57
|
+
Requires-Dist: tox==4.26.0; python_version > "3.8" and extra == "test"
|
|
58
|
+
Requires-Dist: tox==3.28.0; python_version <= "3.8" and extra == "test"
|
|
59
|
+
Requires-Dist: freezegun==1.5.2; python_version > "3.7" and extra == "test"
|
|
60
|
+
Requires-Dist: freezegun==1.2.2; python_version <= "3.7" and extra == "test"
|
|
61
|
+
Requires-Dist: syrupy==4.9.1; python_version >= "3.9" and extra == "test"
|
|
62
|
+
Requires-Dist: syrupy==2.3.1; python_version <= "3.8" and extra == "test"
|
|
63
|
+
Provides-Extra: test-report
|
|
64
|
+
Requires-Dist: coveralls==4.0.1; extra == "test-report"
|
|
65
|
+
Provides-Extra: analysis
|
|
66
|
+
Requires-Dist: black==22.3.0; extra == "analysis"
|
|
67
|
+
Requires-Dist: flake8==7.2.0; extra == "analysis"
|
|
68
|
+
Requires-Dist: autoflake==2.3.1; extra == "analysis"
|
|
69
|
+
Requires-Dist: autopep8==2.3.2; extra == "analysis"
|
|
70
|
+
Requires-Dist: isort==6.0.1; extra == "analysis"
|
|
71
|
+
Requires-Dist: docformatter==1.7.7; extra == "analysis"
|
|
72
|
+
Requires-Dist: mypy==1.16.0; extra == "analysis"
|
|
73
|
+
Requires-Dist: django-stubs==4.2.7; extra == "analysis"
|
|
74
|
+
Requires-Dist: typing-extensions==4.14.0; extra == "analysis"
|
|
75
|
+
Requires-Dist: types-dj-database-url==1.3.0.4; extra == "analysis"
|
|
76
|
+
Requires-Dist: types-python-dateutil==2.9.0.20250516; extra == "analysis"
|
|
77
|
+
Provides-Extra: docs
|
|
78
|
+
Requires-Dist: Sphinx==8.2.3; extra == "docs"
|
|
79
|
+
Requires-Dist: sphinx-rtd-theme==3.0.2; extra == "docs"
|
|
80
|
+
Requires-Dist: docutils==0.21.2; extra == "docs"
|
|
81
|
+
Requires-Dist: Jinja2==3.1.6; extra == "docs"
|
|
82
|
+
Provides-Extra: publish
|
|
83
|
+
Requires-Dist: build<2.0.0,>=1.2.0; extra == "publish"
|
|
84
|
+
Requires-Dist: twine<7.0.0,>=6.0.0; extra == "publish"
|
|
85
|
+
Dynamic: author
|
|
86
|
+
Dynamic: author-email
|
|
87
|
+
Dynamic: classifier
|
|
88
|
+
Dynamic: description
|
|
89
|
+
Dynamic: description-content-type
|
|
90
|
+
Dynamic: home-page
|
|
91
|
+
Dynamic: keywords
|
|
92
|
+
Dynamic: license
|
|
93
|
+
Dynamic: license-file
|
|
94
|
+
Dynamic: provides-extra
|
|
95
|
+
Dynamic: requires-dist
|
|
96
|
+
Dynamic: requires-python
|
|
97
|
+
Dynamic: summary
|
|
98
|
+
|
|
99
|
+
# xdjango-postgres-extra
|
|
100
|
+
|
|
101
|
+
[](https://pypi.org/project/xdjango-postgres-extra/)
|
|
102
|
+
[](https://pypi.org/project/xdjango-postgres-extra/)
|
|
103
|
+
[](https://docs.djangoproject.com/en/6.0/)
|
|
104
|
+
[](LICENSE)
|
|
105
|
+
|
|
106
|
+
`xdjango-postgres-extra` is a maintained fork of
|
|
107
|
+
[`django-postgres-extra`](https://github.com/SectorLabs/django-postgres-extra).
|
|
108
|
+
It extends Django's PostgreSQL backend with features such as atomic upserts,
|
|
109
|
+
table partitioning, views, materialized views, schema management, and explicit
|
|
110
|
+
table locking.
|
|
111
|
+
|
|
112
|
+
The PyPI distribution is named `xdjango-postgres-extra`. The Python package
|
|
113
|
+
and existing imports remain named `psqlextra`.
|
|
114
|
+
|
|
115
|
+
## Compatibility
|
|
116
|
+
|
|
117
|
+
- Django: 2.0 through 6.x (`Django>=2.0,<7.0`)
|
|
118
|
+
- Python: 3.6 through 3.14
|
|
119
|
+
- PostgreSQL: 11 or newer
|
|
120
|
+
- Psycopg: 2 and 3
|
|
121
|
+
|
|
122
|
+
Django 6 requires Python 3.12 or newer. The 2.1.x release line was verified with
|
|
123
|
+
Django 6.0.6 and Python 3.14.
|
|
124
|
+
|
|
125
|
+
## Installation
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
python -m pip install xdjango-postgres-extra
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Use the `psqlextra` database backend in your Django settings:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
DATABASES = {
|
|
135
|
+
"default": {
|
|
136
|
+
"ENGINE": "psqlextra.backend",
|
|
137
|
+
"NAME": "my_database",
|
|
138
|
+
"USER": "my_user",
|
|
139
|
+
"PASSWORD": "my_password",
|
|
140
|
+
"HOST": "localhost",
|
|
141
|
+
"PORT": "5432",
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Add the application when using features that require app registration:
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
INSTALLED_APPS = [
|
|
150
|
+
# ...
|
|
151
|
+
"django.contrib.postgres",
|
|
152
|
+
"psqlextra",
|
|
153
|
+
]
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Existing application code continues to use `psqlextra` imports:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
from psqlextra.models import PostgresModel
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Features
|
|
163
|
+
|
|
164
|
+
- Atomic `INSERT ... ON CONFLICT` handling with `DO UPDATE` and `DO NOTHING`
|
|
165
|
+
- Bulk inserts and upserts
|
|
166
|
+
- PostgreSQL range, list, hash, and default table partitions
|
|
167
|
+
- Time-based partition management
|
|
168
|
+
- Database views and materialized views integrated with migrations
|
|
169
|
+
- PostgreSQL schema creation, deletion, and temporary schemas
|
|
170
|
+
- Explicit model and table locks
|
|
171
|
+
- `TRUNCATE TABLE`, including cascading truncation
|
|
172
|
+
- HStore constraints and expressions
|
|
173
|
+
- PostgreSQL-specific indexes and introspection
|
|
174
|
+
|
|
175
|
+
The upstream documentation remains the primary API reference:
|
|
176
|
+
|
|
177
|
+
- [Documentation](https://django-postgres-extra.readthedocs.io/en/master/)
|
|
178
|
+
- [Installation guide](https://django-postgres-extra.readthedocs.io/en/master/installation.html)
|
|
179
|
+
- [Feature reference](https://django-postgres-extra.readthedocs.io/en/master/index.html#features)
|
|
180
|
+
|
|
181
|
+
When following upstream installation instructions, install
|
|
182
|
+
`xdjango-postgres-extra` instead of `django-postgres-extra`.
|
|
183
|
+
|
|
184
|
+
## Development
|
|
185
|
+
|
|
186
|
+
Create a virtual environment and install the development extras:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
python -m venv .venv
|
|
190
|
+
source .venv/bin/activate
|
|
191
|
+
python -m pip install -e ".[dev,test]"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Set a PostgreSQL test database URL:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
export DATABASE_URL="postgres://psqlextra:password@localhost/psqlextra"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Run the available Poe tasks:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
poe test
|
|
204
|
+
poe verify
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# xdjango-postgres-extra
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/xdjango-postgres-extra/)
|
|
4
|
+
[](https://pypi.org/project/xdjango-postgres-extra/)
|
|
5
|
+
[](https://docs.djangoproject.com/en/6.0/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
`xdjango-postgres-extra` is a maintained fork of
|
|
9
|
+
[`django-postgres-extra`](https://github.com/SectorLabs/django-postgres-extra).
|
|
10
|
+
It extends Django's PostgreSQL backend with features such as atomic upserts,
|
|
11
|
+
table partitioning, views, materialized views, schema management, and explicit
|
|
12
|
+
table locking.
|
|
13
|
+
|
|
14
|
+
The PyPI distribution is named `xdjango-postgres-extra`. The Python package
|
|
15
|
+
and existing imports remain named `psqlextra`.
|
|
16
|
+
|
|
17
|
+
## Compatibility
|
|
18
|
+
|
|
19
|
+
- Django: 2.0 through 6.x (`Django>=2.0,<7.0`)
|
|
20
|
+
- Python: 3.6 through 3.14
|
|
21
|
+
- PostgreSQL: 11 or newer
|
|
22
|
+
- Psycopg: 2 and 3
|
|
23
|
+
|
|
24
|
+
Django 6 requires Python 3.12 or newer. The 2.1.x release line was verified with
|
|
25
|
+
Django 6.0.6 and Python 3.14.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
python -m pip install xdjango-postgres-extra
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Use the `psqlextra` database backend in your Django settings:
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
DATABASES = {
|
|
37
|
+
"default": {
|
|
38
|
+
"ENGINE": "psqlextra.backend",
|
|
39
|
+
"NAME": "my_database",
|
|
40
|
+
"USER": "my_user",
|
|
41
|
+
"PASSWORD": "my_password",
|
|
42
|
+
"HOST": "localhost",
|
|
43
|
+
"PORT": "5432",
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Add the application when using features that require app registration:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
INSTALLED_APPS = [
|
|
52
|
+
# ...
|
|
53
|
+
"django.contrib.postgres",
|
|
54
|
+
"psqlextra",
|
|
55
|
+
]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Existing application code continues to use `psqlextra` imports:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from psqlextra.models import PostgresModel
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Features
|
|
65
|
+
|
|
66
|
+
- Atomic `INSERT ... ON CONFLICT` handling with `DO UPDATE` and `DO NOTHING`
|
|
67
|
+
- Bulk inserts and upserts
|
|
68
|
+
- PostgreSQL range, list, hash, and default table partitions
|
|
69
|
+
- Time-based partition management
|
|
70
|
+
- Database views and materialized views integrated with migrations
|
|
71
|
+
- PostgreSQL schema creation, deletion, and temporary schemas
|
|
72
|
+
- Explicit model and table locks
|
|
73
|
+
- `TRUNCATE TABLE`, including cascading truncation
|
|
74
|
+
- HStore constraints and expressions
|
|
75
|
+
- PostgreSQL-specific indexes and introspection
|
|
76
|
+
|
|
77
|
+
The upstream documentation remains the primary API reference:
|
|
78
|
+
|
|
79
|
+
- [Documentation](https://django-postgres-extra.readthedocs.io/en/master/)
|
|
80
|
+
- [Installation guide](https://django-postgres-extra.readthedocs.io/en/master/installation.html)
|
|
81
|
+
- [Feature reference](https://django-postgres-extra.readthedocs.io/en/master/index.html#features)
|
|
82
|
+
|
|
83
|
+
When following upstream installation instructions, install
|
|
84
|
+
`xdjango-postgres-extra` instead of `django-postgres-extra`.
|
|
85
|
+
|
|
86
|
+
## Development
|
|
87
|
+
|
|
88
|
+
Create a virtual environment and install the development extras:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
python -m venv .venv
|
|
92
|
+
source .venv/bin/activate
|
|
93
|
+
python -m pip install -e ".[dev,test]"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Set a PostgreSQL test database URL:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
export DATABASE_URL="postgres://psqlextra:password@localhost/psqlextra"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Run the available Poe tasks:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
poe test
|
|
106
|
+
poe verify
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.2.0"
|
{xdjango_postgres_extra-2.1.1 → xdjango_postgres_extra-2.2.0}/psqlextra/backend/introspection.py
RENAMED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple
|
|
3
3
|
|
|
4
|
+
import django
|
|
5
|
+
|
|
4
6
|
from django.db.backends.postgresql.introspection import ( # type: ignore[import]
|
|
5
7
|
DatabaseIntrospection,
|
|
6
8
|
)
|
|
@@ -305,13 +307,16 @@ class PostgresIntrospection(Introspection):
|
|
|
305
307
|
"""Gets a dictionary {field_name: (field_name_other_table,
|
|
306
308
|
other_table)} representing all relations in the specified table.
|
|
307
309
|
|
|
310
|
+
Django 6.1 and newer expect a third element in the value tuple
|
|
311
|
+
that describes the database-level ON DELETE behaviour.
|
|
312
|
+
|
|
308
313
|
This is overriden because the query in Django does not handle
|
|
309
314
|
relations between tables in different schemas properly.
|
|
310
315
|
"""
|
|
311
316
|
|
|
312
317
|
cursor.execute(
|
|
313
318
|
"""
|
|
314
|
-
SELECT a1.attname, c2.relname, a2.attname
|
|
319
|
+
SELECT a1.attname, c2.relname, a2.attname, con.confdeltype
|
|
315
320
|
FROM pg_constraint con
|
|
316
321
|
LEFT JOIN pg_class c1 ON con.conrelid = c1.oid
|
|
317
322
|
LEFT JOIN pg_class c2 ON con.confrelid = c2.oid
|
|
@@ -324,4 +329,13 @@ class PostgresIntrospection(Introspection):
|
|
|
324
329
|
""",
|
|
325
330
|
[table_name],
|
|
326
331
|
)
|
|
327
|
-
|
|
332
|
+
|
|
333
|
+
rows = cursor.fetchall()
|
|
334
|
+
|
|
335
|
+
if django.VERSION >= (6, 1):
|
|
336
|
+
return {
|
|
337
|
+
row[0]: (row[2], row[1], self.on_delete_types.get(row[3]))
|
|
338
|
+
for row in rows
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return {row[0]: (row[2], row[1]) for row in rows}
|
|
@@ -74,13 +74,19 @@ class PostgresCreatePartitionedModel(CreateModel):
|
|
|
74
74
|
result = super().reduce(*args, **kwargs)
|
|
75
75
|
|
|
76
76
|
# replace CreateModel operation with PostgresCreatePartitionedModel
|
|
77
|
+
#
|
|
78
|
+
# Django >= 6.0 reduces through `copy.replace()`, which rebuilds the
|
|
79
|
+
# operation as its own class, partitioning options included. Only a
|
|
80
|
+
# plain CreateModel still has to be converted.
|
|
77
81
|
if isinstance(result, list) and result:
|
|
78
82
|
for i, op in enumerate(result):
|
|
79
|
-
if isinstance(op, CreateModel)
|
|
80
|
-
|
|
83
|
+
if isinstance(op, CreateModel) and not isinstance(
|
|
84
|
+
op, PostgresCreatePartitionedModel
|
|
85
|
+
):
|
|
86
|
+
_, op_args, op_kwargs = op.deconstruct()
|
|
81
87
|
result[i] = PostgresCreatePartitionedModel(
|
|
82
|
-
*
|
|
83
|
-
**
|
|
88
|
+
*op_args,
|
|
89
|
+
**op_kwargs,
|
|
84
90
|
partitioning_options=self.partitioning_options
|
|
85
91
|
)
|
|
86
92
|
|
|
@@ -295,8 +295,7 @@ class PostgresSchemaEditor(SchemaEditor):
|
|
|
295
295
|
model, [field.column], foreign_key=True
|
|
296
296
|
)
|
|
297
297
|
|
|
298
|
-
|
|
299
|
-
self.sql_create_fk_not_valid,
|
|
298
|
+
fk_parts = dict(
|
|
300
299
|
table=self.quote_name(model._meta.db_table),
|
|
301
300
|
name=self.quote_name(fk_name),
|
|
302
301
|
column=self.quote_name(field.column),
|
|
@@ -307,6 +306,15 @@ class PostgresSchemaEditor(SchemaEditor):
|
|
|
307
306
|
deferrable=self.connection.ops.deferrable_sql(),
|
|
308
307
|
)
|
|
309
308
|
|
|
309
|
+
# Django 6.1 added a database-level ON DELETE clause to
|
|
310
|
+
# the foreign key statement we borrow the template from.
|
|
311
|
+
if django.VERSION >= (6, 1):
|
|
312
|
+
fk_parts["on_delete_db"] = self._create_on_delete_sql( # type: ignore[attr-defined]
|
|
313
|
+
model, field
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
sql = Statement(self.sql_create_fk_not_valid, **fk_parts)
|
|
317
|
+
|
|
310
318
|
self.execute(sql)
|
|
311
319
|
|
|
312
320
|
# It's hard to alter a field's check because it is defined
|
|
@@ -7,7 +7,7 @@ exec(open("psqlextra/_version.py").read())
|
|
|
7
7
|
with open(
|
|
8
8
|
os.path.join(os.path.dirname(__file__), "README.md"), encoding="utf-8"
|
|
9
9
|
) as readme:
|
|
10
|
-
README = readme.read()
|
|
10
|
+
README = readme.read()
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
setup(
|
|
@@ -37,6 +37,7 @@ setup(
|
|
|
37
37
|
"Environment :: Web Environment",
|
|
38
38
|
"Framework :: Django",
|
|
39
39
|
"Framework :: Django :: 6.0",
|
|
40
|
+
"Framework :: Django :: 6.1",
|
|
40
41
|
"Intended Audience :: Developers",
|
|
41
42
|
"License :: OSI Approved :: MIT License",
|
|
42
43
|
"Operating System :: OS Independent",
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import io
|
|
2
|
+
|
|
3
|
+
import django
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from django.core.management import call_command
|
|
7
|
+
from django.db import models
|
|
8
|
+
|
|
9
|
+
from . import db_introspection
|
|
10
|
+
from .fake_model import delete_fake_model, get_fake_model
|
|
11
|
+
|
|
12
|
+
pytestmark = pytest.mark.skipif(
|
|
13
|
+
django.VERSION < (6, 1),
|
|
14
|
+
reason="Django < 6.1 does not report database level ON DELETE behaviour",
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.fixture
|
|
19
|
+
def fk_target():
|
|
20
|
+
model = get_fake_model({"name": models.TextField()})
|
|
21
|
+
|
|
22
|
+
yield model
|
|
23
|
+
|
|
24
|
+
delete_fake_model(model)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.fixture
|
|
28
|
+
def fk_source(fk_target):
|
|
29
|
+
model = get_fake_model(
|
|
30
|
+
{
|
|
31
|
+
"python_cascade": models.ForeignKey(
|
|
32
|
+
fk_target, on_delete=models.CASCADE, related_name="+"
|
|
33
|
+
),
|
|
34
|
+
"db_cascade": models.ForeignKey(
|
|
35
|
+
fk_target, on_delete=models.DB_CASCADE, related_name="+"
|
|
36
|
+
),
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
yield model
|
|
41
|
+
|
|
42
|
+
delete_fake_model(model)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_get_relations_reports_db_on_delete(fk_target, fk_source):
|
|
46
|
+
"""Django 6.1 and newer expect the values of the dict returned by
|
|
47
|
+
`get_relations` to carry the database level ON DELETE behaviour as a third
|
|
48
|
+
element."""
|
|
49
|
+
|
|
50
|
+
relations = db_introspection.get_relations(fk_source._meta.db_table)
|
|
51
|
+
|
|
52
|
+
assert relations == {
|
|
53
|
+
# a Python level on_delete leaves no ON DELETE clause behind
|
|
54
|
+
"python_cascade_id": (
|
|
55
|
+
"id",
|
|
56
|
+
fk_target._meta.db_table,
|
|
57
|
+
models.DO_NOTHING,
|
|
58
|
+
),
|
|
59
|
+
"db_cascade_id": (
|
|
60
|
+
"id",
|
|
61
|
+
fk_target._meta.db_table,
|
|
62
|
+
models.DB_CASCADE,
|
|
63
|
+
),
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_inspectdb_unpacks_relations(fk_target, fk_source):
|
|
68
|
+
"""`inspectdb` is the one command that unpacks the value tuples returned by
|
|
69
|
+
`get_relations`, so it breaks loudly when their shape is wrong."""
|
|
70
|
+
|
|
71
|
+
stdout = io.StringIO()
|
|
72
|
+
call_command(
|
|
73
|
+
"inspectdb",
|
|
74
|
+
fk_target._meta.db_table,
|
|
75
|
+
fk_source._meta.db_table,
|
|
76
|
+
stdout=stdout,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
assert "ForeignKey" in stdout.getvalue()
|
|
@@ -174,7 +174,12 @@ def test_make_migration_field_operations_view_models(
|
|
|
174
174
|
last_name_field = models.TextField(null=True)
|
|
175
175
|
last_name_field.contribute_to_class(model, "last_name")
|
|
176
176
|
|
|
177
|
-
|
|
177
|
+
# a clone, because Django >= 6.0 strips `indexes`/`constraints` out of
|
|
178
|
+
# the options of the state it detects changes against, and `state_1` is
|
|
179
|
+
# re-used as the target state further down
|
|
180
|
+
migration = make_migration(
|
|
181
|
+
model._meta.app_label, from_state=state_1.clone()
|
|
182
|
+
)
|
|
178
183
|
assert len(migration.operations) == 1
|
|
179
184
|
assert isinstance(migration.operations[0], operations.ApplyState)
|
|
180
185
|
assert isinstance(migration.operations[0].state_operation, AddField)
|
|
@@ -156,6 +156,16 @@ def fake_model_fk_target_2():
|
|
|
156
156
|
|
|
157
157
|
@pytest.fixture
|
|
158
158
|
def fake_model(fake_model_fk_target_1, fake_model_fk_target_2):
|
|
159
|
+
# `check` was renamed to `condition` in Django 5.1 and dropped in 6.0
|
|
160
|
+
if django.VERSION >= (5, 1):
|
|
161
|
+
age_height_check = models.CheckConstraint(
|
|
162
|
+
condition=Q(age__gt=0, height__gt=0), name="age_height_check"
|
|
163
|
+
)
|
|
164
|
+
else:
|
|
165
|
+
age_height_check = models.CheckConstraint(
|
|
166
|
+
check=Q(age__gt=0, height__gt=0), name="age_height_check"
|
|
167
|
+
)
|
|
168
|
+
|
|
159
169
|
meta_options = {
|
|
160
170
|
"indexes": [
|
|
161
171
|
models.Index(fields=["age", "height"]),
|
|
@@ -167,9 +177,7 @@ def fake_model(fake_model_fk_target_1, fake_model_fk_target_2):
|
|
|
167
177
|
fields=["first_name", "last_name"],
|
|
168
178
|
name="first_last_name_uniq",
|
|
169
179
|
),
|
|
170
|
-
|
|
171
|
-
check=Q(age__gt=0, height__gt=0), name="age_height_check"
|
|
172
|
-
),
|
|
180
|
+
age_height_check,
|
|
173
181
|
],
|
|
174
182
|
"unique_together": (
|
|
175
183
|
"first_name",
|