mirror of
https://github.com/django/django.git
synced 2025-10-09 14:59:24 +00:00
Fixed #36580 -- Fixed constraint validation crash when condition uses a ForeignObject.
Follow-up to e44e8327d3d88d86895735c0e427102063ff5b55. Refs #36222.
This commit is contained in:
parent
308f674e6d
commit
8c621e9642
@ -1357,7 +1357,7 @@ class Model(AltersData, metaclass=ModelBase):
|
||||
meta = meta or self._meta
|
||||
field_map = {}
|
||||
generated_fields = []
|
||||
for field in meta.local_concrete_fields:
|
||||
for field in meta.local_fields:
|
||||
if field.name in exclude:
|
||||
continue
|
||||
if field.generated:
|
||||
@ -1368,7 +1368,19 @@ class Model(AltersData, metaclass=ModelBase):
|
||||
continue
|
||||
generated_fields.append(field)
|
||||
continue
|
||||
value = getattr(self, field.attname)
|
||||
if (
|
||||
isinstance(field.remote_field, ForeignObjectRel)
|
||||
and field not in meta.local_concrete_fields
|
||||
):
|
||||
value = tuple(
|
||||
getattr(self, from_field) for from_field in field.from_fields
|
||||
)
|
||||
if len(value) == 1:
|
||||
value = value[0]
|
||||
elif field.concrete:
|
||||
value = getattr(self, field.attname)
|
||||
else:
|
||||
continue
|
||||
if not value or not hasattr(value, "resolve_expression"):
|
||||
value = Value(value, field)
|
||||
field_map[field.name] = value
|
||||
|
@ -3,10 +3,10 @@ import datetime
|
||||
import pickle
|
||||
from operator import attrgetter
|
||||
|
||||
from django.core.exceptions import FieldError
|
||||
from django.core.exceptions import FieldError, ValidationError
|
||||
from django.db import connection, models
|
||||
from django.test import SimpleTestCase, TestCase, skipUnlessDBFeature
|
||||
from django.test.utils import isolate_apps
|
||||
from django.test.utils import CaptureQueriesContext, isolate_apps
|
||||
from django.utils import translation
|
||||
|
||||
from .models import (
|
||||
@ -771,7 +771,30 @@ class TestCachedPathInfo(TestCase):
|
||||
|
||||
|
||||
class ForeignObjectModelValidationTests(TestCase):
|
||||
@skipUnlessDBFeature("supports_table_check_constraints")
|
||||
def test_validate_constraints_with_foreign_object(self):
|
||||
customer_tab = CustomerTab(customer_id=1500)
|
||||
with self.assertRaisesMessage(ValidationError, "customer_id_limit"):
|
||||
customer_tab.validate_constraints()
|
||||
|
||||
@skipUnlessDBFeature("supports_table_check_constraints")
|
||||
def test_validate_constraints_success_case_single_query(self):
|
||||
customer_tab = CustomerTab(customer_id=500)
|
||||
with CaptureQueriesContext(connection) as ctx:
|
||||
customer_tab.validate_constraints()
|
||||
select_queries = [
|
||||
query["sql"]
|
||||
for query in ctx.captured_queries
|
||||
if "select" in query["sql"].lower()
|
||||
]
|
||||
self.assertEqual(len(select_queries), 1)
|
||||
|
||||
@skipUnlessDBFeature("supports_table_check_constraints")
|
||||
def test_validate_constraints_excluding_foreign_object(self):
|
||||
customer_tab = CustomerTab(customer_id=150)
|
||||
customer_tab.validate_constraints(exclude={"customer"})
|
||||
|
||||
@skipUnlessDBFeature("supports_table_check_constraints")
|
||||
def test_validate_constraints_excluding_foreign_object_member(self):
|
||||
customer_tab = CustomerTab(customer_id=150)
|
||||
customer_tab.validate_constraints(exclude={"customer_id"})
|
||||
|
Loading…
x
Reference in New Issue
Block a user